2026-02-08 06:33:34
This lesson is not about deciding whether static typing is “better” or “worse”.
The real goal is this:
To understand when and why the C# compiler makes decisions on your behalf,
and what you gain—and give up—in return.
Once this clicks, method signatures, return types, and compiler errors stop feeling arbitrary.
Humans tend to think like this:
“I’m using a string now,
but later I might want to use a number.”
This way of thinking is completely natural.
Some languages allow this directly.
x = "hello"
x = 10
Why this works:
x has no fixed type
Mental model:
“What matters is what’s inside the variable right now.”
This is dynamic typing.
C# takes a different stance:
“This variable will have exactly one type for its entire lifetime.”
string x = "hello";
x = 10; // Compile-time error
This is static typing.
Static typing means:
The compiler rejects illogical reasoning
before the program is allowed to run.
Example:
string name = "Sabin";
int age = name; // Compile-time error
The compiler is effectively saying:
“This does not make sense.
Do not even try to execute it.”
This is a compile-time error, not a runtime failure.
This distinction is critical.
The compiler warns you early.
These can crash the program in front of users.
“Fail as early as possible—
ideally before the program ever runs.”
A method declaration is a contract.
static bool IsLong(string text)
This line promises:
string
bool
Nothing more. Nothing less.
static bool IsLong(string text)
{
return "yes"; // Compile-time error
}
Compiler logic:
“You promised a boolean.
This is a string. Contract violated.”
string result = IsLong("hello"); // Compile-time error
Reason:
IsLong returns bool
bool to string is invalidIsLong(10); // Compile-time error
Compiler logic:
“This method expects a string.
A number does not fulfill the contract.”
This is one reason C# is favored in large, long-lived systems.
A common misunderstanding:
“Static typing means no flexibility.”
This is incorrect.
The truth:
C# postpones flexibility until it can be expressed safely.
Example concept (preview):
static void Feed(Animal animal)
Dog is allowedCat is allowedSnake is allowedThis is polymorphism.
The pattern is always the same:
var makes C# dynamically typed”C# remains statically typed everywhere.
var still resolves to a fixed type at compile timeA statically typed language is one where the compiler actively blocks human mistakes,
and method signatures are the written contracts that make this possible.
2026-02-08 06:29:17
A wristband at a club
Day 44 of 149
👉 Full deep-dive with code examples
You go to a club. Pay at the door. Get a wristband.
Now you can:
Cookies are digital wristbands!
Visit 1: "Here's your cookie: user=alex"
Visit 2: Browser shows cookie → "Welcome back, Alex!"
| Type | What it means |
|---|---|
| Session | Typically lasts for the current browsing session (but some browsers can restore them) |
| Persistent | Has an expiry time/date; can last days/weeks/months |
| Third-party | Set by a different site than the one you're visiting (often used for ads/analytics) |
Cookies can be used for tracking across websites. That's why many sites ask:
"Do you accept cookies?" 🍪
Cookies are small pieces of data websites store in your browser to remember who you are and your preferences.
🔗 Enjoying these? Follow for daily ELI5 explanations!
Making complex tech concepts simple, one day at a time.
2026-02-08 06:28:55
Every client tool I tried wanted to run my entire business. So I built one that doesn't.
I'm a freelancer. I design things, I build things, and then I have to figure out how to actually get that work to my client.
For years my workflow looked like this: finish the work, zip it up, attach it to an email, type "Hey, here are the files — let me know what you think," and hit send. Sometimes I'd use a Google Drive link. Sometimes Dropbox. Once I even used WeTransfer like it was 2014.
None of it ever felt professional. I'd spend hours making the work look great, then deliver it through a channel that made me look like I was winging it.
So I looked into "real" tools. Dubsado. HoneyBook. Basecamp. Plutio. They all promised to solve this problem. And they did — along with about forty other problems I didn't have.
Every client portal I evaluated came with invoicing, contracts, a CRM, scheduling, time tracking, team chat, and a dozen integrations I'd never configure. The onboarding tutorials were 30 minutes long. The pricing started at $20/month and climbed from there.
I already had an invoicing tool I liked. I didn't need a CRM for my twelve clients. I definitely didn't need "team collaboration" features as a solo freelancer.
All I wanted was a clean page where my client could see their project, download files, and read my updates. That's it. One simple thing.
I couldn't find it, so I built it.
Delivr does three things:
You share files. Upload a deliverable, your client downloads it. One click. No digging through folders, no expired links, no "which version is the latest?" confusion.
You post updates. Write a quick note — "Round 1 designs are ready" or "Waiting on your feedback for the logo." Your client sees it immediately. They can reply right there.
You look professional. Your portal uses your name, your colors, your brand. When a client visits, they see your studio — not some generic tool's interface.
That's the whole product.
This is the part I'm most proud of.
Delivr doesn't do invoicing. It doesn't do contracts. It doesn't do time tracking, scheduling, CRM, team chat, or project templates. It doesn't have a Gantt chart. It doesn't have Kanban boards. It doesn't have AI-powered anything.
And that's the point.
You already have tools for those things. Maybe you use FreshBooks for invoicing and Google Calendar for scheduling. Maybe you use Notion for your own project management. Whatever your setup is, it works. You don't need another tool trying to replace all of them.
Delivr handles the one thing those tools can't: giving your client a clean, branded place to see their work.
The setup takes about five minutes.
You sign up, name your studio, and your portal is live. You create a project, enter your client's email, and they get a link. You upload files and post updates. Your client sees everything in one place.
No onboarding tutorial. No configuration wizard. No "getting started" checklist with 15 steps.
Your client doesn't need to learn anything either. They click a link, they see their project, they download their files. If they want to leave a reply, there's a text box. That's it.
For anyone curious about the stack: Delivr is built with Next.js 14, Prisma, and PostgreSQL. Authentication runs through NextAuth with role-based access — freelancers see the dashboard, clients see the portal. Email notifications go through Resend.
I'm a solo developer running this out of my apartment. There's no team, no investors, no runway. Just a product that solves a problem I had.
Delivr is for the freelancer who has 3-15 clients and wants to look more professional without adding complexity to their workflow.
You're a designer sending brand assets. A developer delivering a website. A photographer sharing edited galleries. A consultant sending reports. A videographer delivering cuts for review.
You don't need a business management suite. You need a clean way to share work and keep clients in the loop.
Delivr is live at delivr.studio. Free to start, set up in five minutes, cancel anytime.
If you're a freelancer and you've ever felt weird about emailing a zip file to a client, this is for you.
I'm building Delivr in public. If you have feedback, there's a feedback button in the app — I read everything. You can also find me on Twitter/X.
2026-02-08 06:26:59
TL;DR: I made an Hybrid Hardware Random Number Generator (HHRNG) using radio noise. You can find the full source code on my GitHub.
Generating randomness is fascinating, and I always wanted to go deeper than just importing some library into my python project and calling .random(). So I set out to build my own library with its own .random() function. Revolutionary, I know.
But I didn't want to just cobble together pseudo-random values. I wanted to build a hardware random number generator (HRNG): one that uses actual physical processes to generate entropy. Think Linux's /dev/random, which harvests entropy from environmental noise: keyboard timings, mouse movements, disk I/O patterns. Windows also have a component named CNG (Cryptography Next Generation) that uses similar inputs.
When I hear noise, the first thing that comes to mind is this:
For the uninitiated, this is an SDR (Software Defined Radio), a real-time visualization of the radio spectrum around me. Notice the constant flickering at the bottom? That's noise, pure and simple. Nothing is transmitting there, yet the intensity is constantly dancing. It's the same static you hear when tuning to an empty FM frequency. If we could capture and measure that movement, we'd have a source of true randomness, unpredictable and nearly impossible to manipulate.
So, based on that, I decided to get to work. Note that I will be using a SDR blog v4 to capture radio signals and compute them.
Here is a global overview of what I needed to do to get this project done:
So, first of all, I needed to find a way to programmatically access my radio data, served as samples. I'd tried this on Windows before with no luck, so this time I went straight to a template that connects over the network on an rtl_tcp server running on one of my Raspberry Pis.
Once everything setup, I was able to receive samples. The code is quite simple, it uses a socket to connect to the rtl_tcp server, and then reads samples from it. Here is a part of the read_samples function, that reads and processes the signals:
As we can see, it computes IQ samples. I and Q refer to two components of a complex baseband signal. They capture both amplitude and phase of the RF signal.
Well, anyways:
The next step is building the "randomizer". It is basically a function that will take, as an input, samples from our SDR, and output a seed we will base our calculations on later.
To do this, I've tried a couple of ways (2, actually), but the most efficient method was using Phase difference.
The phase is the angle of the signal at a given moment. It can be easily calculated using both values of an IQ sample using this formula:angle = atan2(Q, I).
We'll do this for both the current iteration value (n), and the previous one (n-1).
After getting both angles, we will retrieve the phase difference, that will tell us in which direction the signal rotated since the previous sample. It can be done like this: delta = (current_angle - previous_angle + π) % 2π - π
The wrapping in π is to ensure that the result stays between -π and +π, and doesn't make big jumps, like going from 2° to -359° just by rotating 3°.
We got the rotation angle, but that value is still too complex to be properly processed. We will reduce it to a simple bit. The easiest way to do this is by checking its direction:bit = delta > 0 ? 1 : 0
Now that we got a bit, we're simply repeating this n samples times, to get a randomly generated bits array.
But there's a problem. After running the program, and logging some statistics, I observed more 1s than 0s, which isn't great, since the program would tend to go on the 1 side more than the 0 one.
Fixing that is easy, and there are plenty of methods available. I used a very simple one: XOR-ing all the values together, to spread the 1s and 0s. For those who don't know what it implies, it is a simple bit operation:
0 & 0 -> 0
0 & 1 -> 1
1 & 0 -> 1
1 & 1 -> 0
I used that to compare both bits each others, and the results were perfect: we went from a near 20% difference to a max of around 2%.
Finally, for convenience, I'm hashing the results to get an uniform seed to continue with (using SHA256).
We now have our random seed source, but now we have to let the user actually use it.
My first plan: every time someone calls .random(), grab fresh samples from the SDR, generate a seed, and convert it to a float.
This was painfully slow: we were hitting the hardware for every single random number.
Solution: make it hybrid. Use a fast Pseudo-Random Number Generator (PRNG) that gets periodically reseeded with fresh radio entropy, instead of hitting the SDR every time.
This was fairly straightforward to achieve:
Now the code uses the LCG as a base, but it is always reseeded with our seeds taken from our radio samples.
Now, let's build our core random class, that we will call RFDom. We will optionally pass arguments to it, such as the rtl_tcp host, frequency ranges to scan, gain, and other settings.
.random() (returns [0.0, 1.0)) was pretty simple to do, as it used the same code as the youtube tutorial, same for .randint(a: int, b: int), that returns [a, b]. I've just had to implement a include: bool parameter to the LCG API, but that was quite easy.
And done !
After adding .random() -> [0.0, 1.0), .uniform(a: float, b: float) -> [a, b], and .randint(a: int, b: int) -> [a, b] I've looked to the core functions of the python random library, and tried to replicate them. Some of them were really easy, some were quite a bit harder to do. I'm not going to explain all of them, since it's just a bunch of formulas, but here are two that I found quite interesting:
The .choices() func takes at max 4 arguments:
The way it works is pretty simple, even tho it was a bit hard to implement:
population array k times.The cumulative weights represent the range where a number falls into an object, like this:
objects -> ["apple", "banana", "orange"]
weights -> [4, 1, 6]
cum_weights = [4, 5, 11]
=>
apple -> [0, 4)
banana -> [4, 5)
orange -> [5, 11)
k times, based on the weights:we use .uniform(0, max_weight) to get a float value, get the object falling in that range, add it to the list
k elements chosen randomlyThe .shuffle() function is much simpler, but I wanted to talk about the algorithm.
It takes a list as the only argument and edits it in-place (doesn't return it, but changes the original).
To do this, we're using the Fisher-Yates algorithm:
i, a random index j is chosen from the range [i, n - 1], and the elements at positions i and j are swapped.It is represented by this code:
My first idea (before even starting the project) was to try to break it out by overflowing the bandwidth using this tool.
I then made this simple code to have an eye on the values
I ran it, first without any special radio broadcast or whatsoever.
Then, I ran the program, and I observed. No changes at all, but that was predictable. Even with the bandwidth saturated, oscillations in the signal are still there, and the phase difference still works. I also later had an AI analyze the results, which confirmed there weren't any major changes.
This project began with a simple question: where does randomness actually come from ?, and turned into a deep dive into radio physics, signal processing, entropy extraction, and practical limits.
Building this taught me that randomness isn't magic: it's trade-offs. Hardware entropy is slow but truly random. PRNGs are fast but predictable. Combining both? That's where it gets interesting.
Is this generator cryptographically secure ? Probably not. Is it faster than Python's built-in random ? Definitely not. Would I recommend using this in production (or in general) ? Absolutely not.
But that was never the point.
In the end, I won't replace the casual import random when I need randomness, but I learned how this works behind the scenes, even if it's only a fraction of the modern random generators.
If you're interested into seeing the full code, I uploaded it to my GitHub. Usage examples can be found in the /examples/ dir, and installation instructions on the README.
If you have any questions about the implementation, suggestions for improvements, or you've experimented with similar approaches, feel free to drop a comment below. I'm curious to hear what you think!
Here are some links of videos / websites that I used to understand the subject better (not in any specific order). I might've forgotten some.
2026-02-08 06:25:14
At Elanat, right after introducing advanced async capabilities in 4.5, we released 4.6, which included a major upgrade: migrating the CodeBehind framework from .NET 7 to .NET 10. Along with this key migration, we also upgraded the Roslyn compiler from 4.6 to 5, so that developers can benefit from the most complete set of modern tools and performance improvements.
The transition from .NET 7 to 10 brings tangible benefits to .NET-based systems (such as the CodeBehind framework). In terms of performance, deep optimizations in runtime and memory management in .NET 10 lead to a speed increase of about 20-30% and reduced latency in processing concurrent requests. In the area of software development, .NET 10's companionship with newer versions of C# (such as 12) allows for the use of features such as Primary Constructors and Collection Expressions, which result in writing more concise, readable, and efficient code. Security is also improved by updating the base libraries and applying the latest patches. Finally, migrating to this stable version ensures synchronization with the ecosystem and enables access to the latest tools, libraries, and long-term support.
With a different approach to web development in .NET, CodeBehind is worth checking out because it frees developers from unnecessary complexity by focusing on the complete separation of the logic layer from the presentation. This complete separation significantly increases the maintainability and readability of the code, and allows front-end and back-end teams to collaborate in parallel without interference. In addition, its flexible architecture allows you to implement the project exactly according to your needs (from full MVC to Only-View), while automating many tasks significantly increases the speed of development.
CodeBehind on GitHub:
https://github.com/elanatframework/Code_behind
Get CodeBehind from NuGet:
https://www.nuget.org/packages/CodeBehind/
CodeBehind page:
https://elanat.net/page_content/code_behind
2026-02-08 06:23:30
pythondef hello_hashnode(): print('Hello Hashnode!')
专为Hashnode社区定制的内容