1/5 A little know C#/.NET fact is that one can end up in a situation where `this is null` evaluates to true. One just needs a bit of reflection.
2/5 There's good reasons why it's little known. For one, it's kind of useless. The other reason is that doing that starts breaking invariants. For example, C# assumes `this` is always non-null. Call to `this.AndAgain()` should throw, but it won't.
3/5 It also breaks invariants within the runtime. This snippet will work as expected, no surprises:
4/5 But this one will hit a `NullReferenceException` in a spot that the debugger cannot figure out. It has to do with how generic code over reference types gets shared within the runtime.
5/5 .NET Native has an optimization that eliminates the entire method bodies on types that were never seen as allocated that also doesn't play well with this. This makes a good party trick (if the parties you go to are like the parties I go to), but don't do this in real code
• • •
Missing some Tweet in this thread? You can try to
force a refresh
1/N One of my favorite optimizations in the upcoming .NET 7 Native AOT is static data preinitialization. This program prints a circle to the screen. Would you believe me if I said there is no code to compute the circle bytes in the NativeAOT'd executable file of this program?👇🧵
2/N Main difference between Native AOT and the other forms of AOT in .NET is that Native AOT doesn't just pregenerate code - it generates all data structures necessary to run the code, including structures that describe layout of types in memory necessary to do things like run GC
3/N If we're generating data structures for GC, it's not a huge leap to generate "allocated object instances" as well, so we do that too. We also have an IL interpreter that can interpret static constructors. github.com/dotnet/corert/…
1/N I thought it might be interesting to look at how generics are compiled to native code in .NET. A thread.
2/N When generic code is stored in IL on disk (as produced by e.g. the C#/VB/F# compiler), single generic method has a single method body. This method body is only runnable on the abstract CPU that the .NET compilers target. To run it on real hardware, it has to be translated.
3/N Real CPUs have pesky details that the abstract virtual machine doesn't care about - like registers and calling conventions.
1/n It has always bugged me that I can't run my 64-bit C# games on MS-DOS. Today I fixed that. A thread.
2/n Windows EXE files consist of two parts: a DOS program that prints "This program cannot be run in DOS mode", followed by a header that Windows understands.
3/n In a way, all EXEs are DOS programs - they're just not very useful DOS programs. One day I found this project (that deserves way more GitHub stars than it has): github.com/Baron-von-Ried…
2/5 Implement enough x86 Windows support in CoreRT so that we can build the game for it (previous attempt was x64; but the x86 CPU instruction set is more compact): github.com/dotnet/corert/…
3/5 Get rid of string literals in the game and get rid of class constructors. I put those changes in a branch because I'm not so proud of it (just don't want to spend more than a day on this): github.com/MichalStrehovs…
1/15 When compiling .NET ahead of time, the hardest question to answer is what code to compile.
2/15 For many non-.NET languages it's enough to compile the closure of Main(): start with Main() and compile all methods called from there transitively.
3/15 But .NET offers unconstrained reflection: one can `Type.GetType` a text string literally downloaded from the internet and call methods on that type