Why shudder? Sure, devops to VMs instead of .NET Core containers isn't as nifty but there is something to be said for code that can run for 5+ years without needing to be touched. Zero-maintenance is a big selling point but right now MSFT is requiring us to update ALL of our code just to rev the version every 36 months (not counting security issues -- we lost more than two weeks of productivity eradicating the Newtonsoft exploit at my last company).
Staying with .NET Framework is a factor that increases talent attrition and the cost because less people are willing to work with it. This is without discussing technical downsides.
> Staying with .NET Framework is a factor that increases talent attrition
100% this. If a company is not willing to move the product forwards because "there is no need to" then I would be looking else where. .NET Core will be a decade old very soon and a company not willing to move to that tech stack is just pure neglect.
You're assuming a workshop where there's just one significant app. The last several places I've worked there were dozens of apps, microservices, and APIs; some of the old and stable APIs were .NET Framework and those never needed to be touched. We built all of the new hotness using .NET Core, Blazor, and whatever the JS framework de jour was, all without needing to touch the old, stable, and working Framework code happly humming along in its VM.
Last time I tried I had troubles. My understanding is open generics (like List<T>, without specifying T) don’t fully compile because Native AOT lacks a JIT to handle unspecified types at runtime. Closed generics work fine, though, as they’re fully known at compile time. Am I wrong in my thinking?
This does not line up with the implementation. You may want to ask in DotNetEvolution or dotnet/runtime discussions as there you can get a definitive answer why something didn't work - most of the time it is best to avoid such assumptions.
Open generics simply propagate type parameters down - T: class produce shared method bodies, as they do with the JIT with the type being passed implicitly. For T: struct the corresponding code is fully monomorphized. This is not related to JIT at all where the main distinction with NativeAOT is when compilation happens.
All generic scenarios are supported. Unbound un-analyzable reflection as well as anything that requires JIT like assembly loading or reflection emit - this doesn't work for obvious reasons.
Only generic scenarios that can be resolved and compiled at build time are supported in NativeAOT. So, the statement that “all generic scenarios are supported” is overly broad. I’ll try to avoid such assumptions :).
ILLink has definitive knowledge about the types present in the program, including generic instantiations, which is what allows ILC to compile the program. You cannot introduce new types at runtime when using NativeAOT, and all callsites and reflected upon members are either statically known or brought in by one or another form of annotation. This is not related to JIT because the only difference in generic handling is when the compilation takes place. It is handled by the same compiler back-end being fed the same information. In fact, this also applies to trimming with JIT publish modes. Generics themselves are only tangentially related to reachability analysis. You are misunderstanding the way this works, this isn't Unity's Mono.
Putting in more practical terms - had NativeAOT not supported List<T> where T is an open generic, most hello-world scenarios would not work at all. And yet, somehow, by divine intervention, ASP.NET Core, DapperAOT, Avalonia, Uno as well as MAUI iOS under Simulator, even damn WinForms that was never made with NAOT in mind (with a helper package), and so on and so forth - all complex applications, work under NativeAOT.
Better later than never, I was disappointed with NGEN capabilities, given the Delphi influences on .NET.
Microsoft research had Sing#, System C#, which never came to us, Mono AOT had its issues, and finally Windows 8.x MDIL/Bartok, UWP .NET Native, which were still special cases.
I always vouched the opinion that had .NET supported AOT properly since the beggining, there would have been much less people reaching out to C and C++, as one of the reasons was getting real executables (same applies to Java, and the issue AOT until recently being a commercial JDK feature for deep pockets).
.NET has come to be a very solid, performant, cross-platform, productive runtime. I always come back to it for most projects. Thanks to everyone involved!
27 comments
[ 3.3 ms ] story [ 65.9 ms ] threadEF 9 has some good fixes, and even better, the better, works on .NET 8.
I discovered last week that .NET Framework v3.5 is still technically supported. Shudder.
100% this. If a company is not willing to move the product forwards because "there is no need to" then I would be looking else where. .NET Core will be a decade old very soon and a company not willing to move to that tech stack is just pure neglect.
And that's when you realise SDK style projects are much nicer than the old project files. The tooling has massively improved in the past decade.
I know it's not part of "standard" c# 13 out-of-the-box
Open generics simply propagate type parameters down - T: class produce shared method bodies, as they do with the JIT with the type being passed implicitly. For T: struct the corresponding code is fully monomorphized. This is not related to JIT at all where the main distinction with NativeAOT is when compilation happens.
All generic scenarios are supported. Unbound un-analyzable reflection as well as anything that requires JIT like assembly loading or reflection emit - this doesn't work for obvious reasons.
Putting in more practical terms - had NativeAOT not supported List<T> where T is an open generic, most hello-world scenarios would not work at all. And yet, somehow, by divine intervention, ASP.NET Core, DapperAOT, Avalonia, Uno as well as MAUI iOS under Simulator, even damn WinForms that was never made with NAOT in mind (with a helper package), and so on and so forth - all complex applications, work under NativeAOT.
You can't generate new code at runtime (Reflection.Emit) with AOT.
Microsoft research had Sing#, System C#, which never came to us, Mono AOT had its issues, and finally Windows 8.x MDIL/Bartok, UWP .NET Native, which were still special cases.
I always vouched the opinion that had .NET supported AOT properly since the beggining, there would have been much less people reaching out to C and C++, as one of the reasons was getting real executables (same applies to Java, and the issue AOT until recently being a commercial JDK feature for deep pockets).