.NET languages are amazing. It's fairly easy to program in any style in C# now: imperative, or OO with massive inheritance hierarchies, or even functional-only with LINQ and things like switch expressions and primary constructors (mentioned in the article). C# now also has top-level statements, so no need for `public class Main { public static void main() {}}`.
The .NET standard library is by far the biggest I've ever seen—it's not merely 'batteries included'; it's 'everything under the Sun included'. NET also comes with a straightforward package manager for third party libraries (NuGet).
There are a variety of development environments available—VS2022, VS Code, Rider, command-line tools. Speaking of command-line tools, the `dotnet` bootstrapper makes it really easy to get started with any sort of project.
The compiler and static analysis tool set, Roslyn, is itself increasingly written in C#, having migrated from C++. With NET 7, code can now be compiled to native binaries ahead-of-time, and there's even an experimental LLVM backend[1].
One can write code for almost any use case (except perhaps embedded) with .NET. It really needs to be used more.
And needless to say: .NET is open-source and cross-platform.
How so? Do you mean it doesn't support ephemeral ftrace-based tracing or something? That seems unlikely to be true given core CLR features like reflection as well as Microsoft's extensive history of embedding .NET into services and devices.
There could be sufficiently small and performance critical things that you really need to use C/Rust and avoid the overhead of garbage collection all together, or you need deterministic timing and so can't use GC.
The performance ceiling of C# is extremely high now though, if you use the low level features. Unsafe blocks, even simd intrinsics! But at that point you aren't really doing C# so much, but at least you can dip into those features for performance critical parts of your code without having to pull out a new language and compiler and complicate your workflow and build tools.
> But at that point you aren't really doing C# so much
I wouldn't really agree on this point.
Unsafe blocks have been a feature since C# 1.0 They may not be the default way of writing C#, but they've always been a natural and integral part of C# and have extensive use internally to ensure that interop can work and extra performance is available where possible.
SIMD acceleration has likewise been a part of the BCL (standard library) for nearly 10 years now and is just as integrated behind the scenes. It being part of the formal BCL makes it even more "standard" than the equivalent in C/C++ where such functionality is relegated to compiler specific headers/extensions.
SIMD code itself is also very idiomatic C#. There is nothing really different about utilizing the APIs, the only difference is in how you think about handling your data. Needing to think differently about how data is handled for some contexts is applicable to many domains in C# (and programming in general). It's no different than making code work with async or multi-threading ;)
Simply put, all these features are still C# and I don't think its necessarily good to say that using them means you're not really writing C# anymore. I view it as a disservice to the language, its extensibility, and power. It also leaves a connotation that you might be better off writing C/C++ instead, which is often not the case.
Embedded is a very barren environment. One where bytes of memory and individual clock cycles can matter a lot.
This is just not the environment a memory managed language, running atop a virtual machine runtime is suitable for. You'd have to strip all that away, and then you'd just be left with C# syntax, but it would be very far from being C# and would not be compatible with any standard C# library, framework or platform.
For a lot of embedded work, even Rust is having a difficult time getting traction. Even the C++ Standard Library doesn't fit on many of the systems folks are working on, let alone the STL.
The system I'm working on at my day job has about 1meg of Flash and, IIRC, 128k RAM. It was reduced in resources to save cost (disposable device). The one I'm working on at home has about 4M Flash and 256k RAM. One of them is making liberal use of the STL and I know both have Python implementations available.
Tiny, memory constrained devices are still around, but they're a smaller and smaller part of the pie every year.
You do realize Java was literally made for set top-boxes and the like? Sure, there are much more resource-constrained embedded devices as well, but byte code takes up much less space than machine code, plus a naive interpreter can be really really small, so it’s not an unworkable path.
I specifically left embedded out because I didn't really want to make assumptions about CLR byte code running within the constraints of such environments. I've only ever programmed in C++ on embedded devices, so I can't actually comment on CLR (ergo the perhaps in my comment).
There actually was a sort of embedded-systems variant of .NET called ".NET Micro" but it fell off a few years back (last release was back in 2015) and I think it had some high-ish minimum requirements (e.g. it's not running on a PIC or the AVR arduinos)
I should do some sort of write up of just .netMF, but I don't honestly recall too much about it in a general sense, since most of my time was spent in the weeds optimizing code.
Modern embedded is not the same as it was in our youth. Embedded platforms then were 8-bit, 1-4 MHz and 64K of RAM would be a luxury. Often that address space would be shared with ROM.
Now we take multi-core, 64-bits, gigabyte address spaces, memory protection and multi-tasking Unix-like OSs for granted most of the time. Except for the most stringent requirements (such as hard real time or very constrained power budgets) that we find small bare metal platforms.
And those are real fun to do ( but not as much fun to debug).
I believe Vector4.Transform(Vector4, Matrix4x4) is my hottest path right now, but as I get into more complex scene graphs, Matrix4x4.Multiply(Matrix4x4, Matrix4x4) will likely pop into the profiler.
There are some more cases to be improved. `Matrix4x4.Multiply` in particular I need to update to use a proper SIMD implementation rather than its current scalar implementation.
If you have any other core scenarios where it's important, let me know and I can try to focus on them sooner, rather than later ;)
Raw. Software only. Pixel shading is done in code with methods defined per scene object. The delivery to eyeballs is via streaming images to browser over web socket. Absolutely no GPU is required (this is a central design objective).
I concur! Coming from Java world to .NET/C#, I was initially very sceptical of Microsoft's offering. Now, I expect to be paid a heavy premium if I ever have to go back to Java.
Also, there's a ton of world class third party tooling around .NET that really makes everything better.
Shout-out to LINQPad for saving me literally 100s of hours on testing, queries and quick POCs.
As a long time Java professional who hasn't experienced .NET what would you say are the biggest advantage points of .NET vs a typical modern Java setup with say, IntelliJ, SpringBoot, maven/gradle etc?
I have very little experience with Java, but I tried building a web app with Spring Boot once. Figuring out even the most basic things, like how to get server-side templates to work, took forever. Many things documented around the web just flat out didn’t work. I got it to a workable state though.
In the modern ASP.NET Core, things are much better organized and documented. The framework has far less magic involved. No magically auto-generated repositories, no @Autowired magic, and far less use of annotations. Things just make more sense.
As for the language itself, C# is nicer in many regards. Even basic things like properties instead of hand-written or Lombok-generated getters and setters, or operator overloading where it makes sense, lead to clearer code.
Regarding IDEs: I hate Visual Studio, but JetBrains Rider is basically IntelliJ for C#.
Its literally IntelliJ for c# lol. Same base system just tied into the Roslyn compiler chain and using their proprietary .NET debugging system instead of whatever they use for the JVM. And while I still use VS at work on personal projects (in both c# and f#) I've switched fully over to Rider and enjoying the experience a great deal, so anyone used to IntelliJ can get a pretty comparable experience from their IDE right out.
Not sure when did you try it out, but there are things like Spring Initializr where it really is just clicking together your initial setup.
Also, there are plenty of old, no longer working code samples on the internet for spring, but the official documentation is really great and should be preferred over some random blog that likely 6 years old already.
I tried Spring Initializr. I made the mistake of picking human-friendly Freemarker templates instead of the XML abomination that is Thymeleaf, and things went to hell.
And can you show the nice official documentation? All my searches back then pointed me only at blogs and stuff. All of them full of outdated advice — for example, the version I started with was one of the first to change the default file extension for Freemarker from `.ftl` to `.ftlh` for some invalid reason, but none of the online blogs were updated for it, I found out after a few hours of trying out random things when I stumbled upon the change log for that release. (The reason was allegedly “security”, but what stops them from disabling the insecure features and keeping the extension?)
Another thing that was woefully under-documented was the default security thing, it also took me forever to figure out how to get a login page showing and working.
Is .NET a viable platform for cross-platform data analysis and visualization tool development now? Python is king here, it sure has everything, but I'm tired of its non-type-safety.
From what experience I've had, C# is a very ergonomic language, with good balance between an expressive static type system and do-whatever-when-needed dynamic features.
Another language I'm looking at is TypeScript, since everything's in browser anyway, and browsers got fast.
> Is .NET a viable platform for cross-platform data analysis and visualization tool development now?
I'm not sure there's anything as powerful as Pandas + Numpy + Matplotlib in C# (or almost any other language, for that matter), but it looks like there are a few attempts.
I tried C# recently again, after having migrated to use JS/TS and Node.Js as my main stack for years.
What put me off was how cumbersome it seemed to be. Maybe I’ve just been spoiled by JS/TS, but where are the following features (which I believe to be quite basic)?
- Union types
- Object literals
- Functions as first class citizens
I get that C# is supposed to be a purely OO language, but in this day, the most useful languages are multi-paradigm.
People like to dish on JS/TS but IMHO one reason why they became so popular is overlooked. There’s just something so direct and unceremonious about programming in JS, and with TS you get strong expressiveness as well.
Until and unless the .NET languages have that it will be hard to pull me away.
Union types are a gap, although records and switch expressions will get you much closer than was previously possible.
Object literals are a thing, they’re called anonymous types. You just new them up. And functions can be passed around as first class objects, with some minor type boilerplate in a few places.
There are a few places where you have to adjust to different naming conventions and types are obviously stricter but my experience is that for the most part modern c# has all the things I like about TS/JS.
It is worth mentioning the c# team is taking a serious look at Union types finally. Considering the runtime already has a version in f# I'm curious how it goes on the c# side of the house (I know semantics are different between the two languages so can't necessarily be 1:1)
Could you elaborate? Do you specifically mean support for 64-bit arrays or something?
.NET in general has great support for 64-bit platforms and while it wasn't the default target for .NET Framework, it has been the default target for .NET [Core] for years.
We notably don't support single-dimensional arrays that have a 64-bit length or individual objects in general being that large. However, that also isn't necessarily a bad thing as there is a large difference between your overall application supporting more than 32-bits of memory (decently common and generally good) and individual allocations using more than 32-bits of memory (not so common and generally not good to have).
If you're creating individual allocations that are larger than 4GB, you're likely not correctly accounting for devices that only have 4-8GB of memory, are more prone to cause memory thrashing, and may end up negatively impacting other parts of the system since such allocations place special restrictions on how the GC can/should interact with the data or in the case of data that is or contains reference types it can add large numbers of additional references for the GC to track.
For such scenarios, it's often better to manage your memory differently, to support streaming/buffering where possible, and if it is the rare scenario that actually necessitates such large allocations to use things like NativeMemory to bypass the GC alongside Span or the SequenceReader/Writer APIs to work with smaller chunks of data. This also allows the data to be thought about differently since the algorithm you'd use to work with small to medium sized data is not necessarily the same algorithm you'd want to use when working with large to huge data. The time cost required to process multiple GB of memory is significantly different after all, as is the cache locality and other aspects.
Spans are certainly a bit unfortunate, and are something I wish were backed by `nint` instead of `int`. But those came to the language later and it wasn't covered as part of the initial design.
That being said, it is largely in the same boat where if you're working with more than 2GB of memory in a single allocation, you're not necessarily going to have a good time. Even if your phone has 12GB of memory, you in practice get a much smaller portion of that available for actual usage and you don't want to cap out the available RAM either since that will cause thrashing and other issues.
75-80% of available physical RAM is about what you want to cap out at, and that's if you're the only app really using any resources.
MemoryMapped files notably support 64-bit values today and have since they were introduced. As have streams in general.
Streaming tensors can make sense and is necessary with extremely large models. The CPU cannot handle all data at once and the cost of loading everything from disk is often expensive, so you'll want to balance loading in data you need in the short term with data that isn't needed anymore or will only be needed in the long term.
Streaming or otherwise chunking your data can likewise help with parallelization and while there are some domains where chunking isn't possible, streaming always is. It just comes down to data size to determine if its beneficial or not.
Plus many "embedded" scenarios have an OS capable of running regular .NET as well.
The problem of .NET versus other alternatives like Java (as an example), is the 2001 - 2014 legacy of being mostly Windows focused, which hinders the choice of libraries and tooling versus those alternatives.
For example, coming back to the embedded scenario, .NET has nothing comparable to PTC, Aicas or the endless variants of JVMs shipping on copiers, electricity meeters, M2M gateways and such.
After .NET Core I was one of the people that really thought "maybe Microsoft has changed at least in the .NET division, let's not be prejudiced, if they want to make FOSS let's give it a try". But of course they showed their hand and I'd have to be a fool to believe this is a platform worth investing myself in.
It's even killed my enthusiasm with F#, despite it almost growing into its own thing after how much MS has neglected it.
I don't want this to sound like I'm defending having a proprietary debugger, but a lot of the tools that people use are proprietary even while they think they're using FOSS. For example, Visual Studio Code + Python? All that IntelliSense is a proprietary Microsoft binary and can't be used with non-Microsoft products. Are you running an open-source fork of VSCode? You can't run that plugin. Want VSCode + JavaScript + IntelliCode? Proprietary again.
As the link notes, there is Samsung's open source debugger, but it's not the one that is used by any of the common IDEs (VSCode, Visual Studio, or Rider).
It's certainly not an amazing situation that I want to be defending, but most people look past the fact that they're running plenty of proprietary stuff inside their VSCode editor and if you're looking past proprietary extensions for JS or Python, it makes sense to also look past proprietary extensions for C#.
The perfect example of why Microsoft can't be trusted. VSCode had a great open source Python extension which everyone used. Then Microsoft hired the developer and switched to recommending their closed source extension instead. VSCode extensions are then licensed so they cannot be used with VSCode forks. It really shows Microsoft's mindset.
To summarize: .NET, the entire platform and language and ecosystem and everything, should be completely and utterly avoided because:
- the ability for the open-source extension to, at the user's option, additionally interface with existing closed-source tools (in a non-license-affecting way), was added
- they wanted to limit hot-reload in .NET 6 because of quality issues (but reverted after people disagreed)
- Microsoft's debugger isn't open-source (even though there still is a popular open-source one)
- a clerical error resulted in all the repos the .NET foundation were administrating getting moved to the .NET foundation's GitHub, including ones that weren't supposed to (which, being incredibly obviously a mistake, was instantly reverted)
If you call these things 'showing their hand', I would call that motivated reasoning. I consider it impressive that a site dedicated to collating all the idiotic drama in order to smear the participants, can only find four examples, despite targeting literally Microsoft. By comparison if you started trying to collate the community drama for Rust or Golang (or god forbid Java) you'd be at it all day.
It was not a clerical error. E.g. nobody typed wrong command or something. That was a decision .NET Foundation heads made and executed. AFAIR https://github.com/clairernovotny
> was instantly reverted
No, it was not instantly reverted. Took us over 1 month to get our repository back under our full and undivided control.
My biggest problem with .NET, is how fast it's moving. Slow down! Also increase LTS support timelines. Default is 3 years, which is just not enough. Ubuntu LTS is the model to follow.
I'll second the request for increasing the length of LTS! While it's technically 36 months it turns out to be 24 to 28 months in practice because my shop will not upgrade our projects immediately -- and we do have to update our projects since we have a TON of AWS lambda functions in C#. After the last "Oh crap, the deadline to upgrade" death march we started having serious discussion about dropping C# for new lambda development and going with Python. If the LTS were extended to at least 5 years, or there was some sort of bug-fix-only support beyond the current 3 year TLS then the ground-swell toward python where I work would stop.
It's not that things break when upgrading, it's that we need to call a halt to new feature development and go upgrade all lambda runtimes before the deadline because AWS won't support deploying lambdas running deprecated .NET Core versions. In the last couple years we've had to stop everything to make sure all of our 2.x code was up to 3.1 (6 wasn't out quite yet) and a year alter we moved everything up to net6 to stay within the AWS deployment support.
Agreed! the move from 2.x to 3.x was pretty easy, but going to 6.x was painful, and why have a LTS that lasts only slightly longer than the follow-on 7.x version? Half of each cycle we don't know if we should update, to which version, or just wait.
I think these are just growing pains. The migration from 6 to 7 to 8 is going to be more fully representative of how .NET is going to work. There was a lot of stuff with Core 2/3 that wasn't fully fleshed out and is generally why we avoided building anything in it. And yes, 4.8 is still getting security updates, but .NET 4.x is effectively dead and almost no new projects should be built in it (yes Winforms people I hear your screams)
Like others have chimed in here, it's really not so bad to step away from the Microsoft products while using .NET. I have worked on a solution where all the devs used MacOS running a mix of VS Code and Rider to develop on, while hosting the application on Linux with a PostgreSQL data store. None of it was difficult to setup and configure. There was consistently a bit of an on-ramp for devs who had never used MacOS before (a really common trait among .NET developers), but other than that things were peachy.
Microsoft employee here. We were "urged" to use .NET 6 last year when starting a new project internally and the transition has been quite hard. The learning curve is extremely steep. It took us almost two weeks to work out some basics because the online documentation, a lot of open source projects and what the latest .NET templates look like are very different. The team spends a lot of time figuring out how something is done in .NET and we stumble over a lot of online advice which is dated or plain wrong because it dates back to .NET Framework or .NET Core times. .NET 6 seems to be different to .NET Framework and different to .NET Core in the way it handles even simple things like namespaces, using declarations and other language features. Maybe when we get good at it we will like it but so far it's been quite a journey and I'm not sure we would choose it again if we didn't have to.
I find this extremely surprising. What were you using before?
I've done multiple Framework 4.8 to .NET 6 migrations and the issue is almost always compatibility with new libraries. Language issues rarely if ever come into play.
What C# language version were you working with before?
We mention in our job descriptions clearly .NET 4.8 and still get 100s of applications.
In the meantime we are working on upgrade to the new .NET but it will take at least couple years.
> .NET 6 seems to be different to .NET Framework and different to .NET Core in the way it handles even simple things like namespaces, using declarations and other language features.
Those are C# language features, not necessarily .NET 6 features:
Yeah, those are optional language features. Namespaces with braces work just fine, and any other language features that are too fancy can be easily disabled in your .csproj (sometimes by downgrading to an older LangVersion).
This is just the decay of knowledge over time and laziness combined.
From a quick glance internally, the overwhelming majority of repos are using an antiquated build/packager that while it might have been useful a decade ago is a productivity killer today.
The newer build / package system used publicly is light years ahead and provides a boon in productivity.
Not really sure why so many services in MSFT still run .NetFramework when “just” migrating over can lead to sometimes order of magnitude increase runtime performance and decreased resource consumption.
I think one of the real reasons is internally, most of the leads aren’t aware of it. There should be more evangelizing of the .NET team across the different orgs
Post author here -- There are lots of resources for teams within Microsoft. Please reach out and we can help you speed up that process. Contact info in my profile.
We work super closely with teams and often post about their fine work and even finer results on our blog.
Why... Are the names of everything so confusing? Why does the naming scheme hsve to change with whst looks like every release of the language or framework or whatever. To an outsider all the different .net (core|framework| whatever) names just look.. like the same thing.
I hate the naming scheme but I get it up to a point. Core has VERY breaking changes from Framework (killing off libraries although some of them have been unkilled to varying degrees is probably the biggest one). Frankly I wish they'd stuck with Core as the Post Framework name instead of being like "okay now we are just .NET 5!
This feels really incorrect or perhaps you're a complete novice to .NET or fresh out of school. .NET 6 is line-for-line compatible with nearly everything you'd encounter online. The core API hasn't changed, there's certain edges that have changed from .NET Framework to .NET, including where certain libraries might have been moved but I've migrated multiple projects now and the only issues were typically related to either using very old frameworks that had changed their API or changes to build systems (which admittedly are tedious).
I agree that the OP sounds very incorrect, but there is one thing that is notably different, and that would be web development. The classic ASP.NET and the modern ASP.NET Core are not compatible with each other, and have different development styles in some areas. But other than that, most code out there should work with both.
Lots of good feedback in this thread so far that I agree with. If I'm doing Windows stuff, yeah, it's great. Lots of new good stuff. My next project is going to be Azure based, so I'm sure I'll be back in the world a bit.
There's a lot you can do with C# with .NET, game engines, cross-platform tools and so on.
Why? Simple. It's literally the fastest framework in the world. This save us a ton of money on cloud costs.
I can support millions of DAUs with a 3-node K8s cluster running .NET7 instead of a 50+ node cluster with Python or node. Just simpler, without npm package dependency hell, and produces a nice clean single file executable.
The bulleted list in the design point section is intended as a high-level summary. We may do another post later that is part-way between the bulleted list and the post as a whole. Perhaps that would be the last post in the series.
I’ve been serving as an architect for two teams, one working with Spring Boot and the other with .NET Core.
Quite frankly, they seem to be roughly equivalent in everything, from features to developer experience to performance. We ended up preferring Flyway for db migrations for both platforms.
I run .NET trading and data manipulation apps on Linux 24/7, can't complain. Modern .NET is very cross-platform and was one of the motivators for my moving to Linux. I could write my code in Rider/VSCode and deploy without a lot of fluff in the background.
I didn't really encounter any issues when moving from 4.8 to Core 1.1 then 3.1 then 6. There were a few cases where a library wasn't available the first few days but that was mainly during the 4.8 transition. After that, most libraries migrated to using .NET Standard.
Probably the only gotcha when moving cross-platform was platform specific code. In my case, I had some very minor code to resize a console window when run interactively that was exploding.
Overall, I can't speak for the desktop story but services, command-line apps and web-apps were literally copy/paste binary to run or git clone and open in Rider to edit.
People get caught up on versions of the framework. Handy guide:
.NET Framework (v1.0-4.8) - 4.8 Currently still supported, but don't build anything new in it. It only gets very minor updates. Not cross platform (Mono can help, but euuughhh), slower, stuck with C# 7.3.
.NET Core (v1.0-3.1) - Out of support, transition period between .NET Framework and modern .NET. Cross platform support, some support for AOT compile.
.NET (v6-8) - LTS every other version starting with 6, 36 months LTS, cross platform, magnitudes faster than .NET Framework. Successor to Framework and Core. Many features of .NET Framework have been abstracted to NuGet packages.
.NET Standard (v1.0-2.1) - Interop API specification for Framework/Core/.NET. Write a class library that targets .NET Standard and you can use it in more than one runtime. You'll see a lot of NuGet packages target Standard. If you're writing a class library you should probably target Standard.
"Core" products/packages - Many packages/libraries have been renamed to include "Core" in the title. ASP.NET Core, Entity Framework Core, etc. These are libraries/packages that only have implement their core functionality. For example, ASP.NET Core has some basic implementations, but does not include things like Web API, MVC, Authorization, Razor. If you build an ASP.NET Core project you'll be pulling in a lot of packages based on your needs. The features/libraries are more atomic and less reliant on a full version update of ASP.NET Core.
I've been one of those purist native-first guys, but as of late I brought up a custom GUI app in question of days with XAML studio and winUI gallery (0 background), piloted with Powershell (in Notepad++), and it does the trick. happy to enter WPF and .net, almost by accident.
1. Microsoft is a pretty big contributor to Linux at this point. Their cloud arm pretty much forced their hand and I don't see that story changing anytime soon. .NET on Linux has been great in my experience.
2. Some libs are, others are decidedly _not_ enterprise driven. The ecosystem is pretty large so there tends to be a lot of options with most packages. Just take a look here, https://github.com/thangchung/awesome-dotnet-core, the ORM section has things as big as nhibernate, which is about as heavy-handed as it gets, to things like Dapper which is about as lightweight as you can get.
115 comments
[ 3.1 ms ] story [ 211 ms ] threadThe .NET standard library is by far the biggest I've ever seen—it's not merely 'batteries included'; it's 'everything under the Sun included'. NET also comes with a straightforward package manager for third party libraries (NuGet).
There are a variety of development environments available—VS2022, VS Code, Rider, command-line tools. Speaking of command-line tools, the `dotnet` bootstrapper makes it really easy to get started with any sort of project.
The compiler and static analysis tool set, Roslyn, is itself increasingly written in C#, having migrated from C++. With NET 7, code can now be compiled to native binaries ahead-of-time, and there's even an experimental LLVM backend[1].
One can write code for almost any use case (except perhaps embedded) with .NET. It really needs to be used more.
And needless to say: .NET is open-source and cross-platform.
[1]: https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-...
Heh, I was afraid of being called out as a Microsoft shill. You're right, though—.NET really is that good.
I'll go ahead and say that open-sourcing the .NET ecosystem is the single best decision that Microsoft has taken in recent history.
any
use case (except perhaps embedded) with .NET.
How so? Do you mean it doesn't support ephemeral ftrace-based tracing or something? That seems unlikely to be true given core CLR features like reflection as well as Microsoft's extensive history of embedding .NET into services and devices.
The performance ceiling of C# is extremely high now though, if you use the low level features. Unsafe blocks, even simd intrinsics! But at that point you aren't really doing C# so much, but at least you can dip into those features for performance critical parts of your code without having to pull out a new language and compiler and complicate your workflow and build tools.
I wouldn't really agree on this point.
Unsafe blocks have been a feature since C# 1.0 They may not be the default way of writing C#, but they've always been a natural and integral part of C# and have extensive use internally to ensure that interop can work and extra performance is available where possible.
SIMD acceleration has likewise been a part of the BCL (standard library) for nearly 10 years now and is just as integrated behind the scenes. It being part of the formal BCL makes it even more "standard" than the equivalent in C/C++ where such functionality is relegated to compiler specific headers/extensions.
SIMD code itself is also very idiomatic C#. There is nothing really different about utilizing the APIs, the only difference is in how you think about handling your data. Needing to think differently about how data is handled for some contexts is applicable to many domains in C# (and programming in general). It's no different than making code work with async or multi-threading ;)
Simply put, all these features are still C# and I don't think its necessarily good to say that using them means you're not really writing C# anymore. I view it as a disservice to the language, its extensibility, and power. It also leaves a connotation that you might be better off writing C/C++ instead, which is often not the case.
This is just not the environment a memory managed language, running atop a virtual machine runtime is suitable for. You'd have to strip all that away, and then you'd just be left with C# syntax, but it would be very far from being C# and would not be compatible with any standard C# library, framework or platform.
For a lot of embedded work, even Rust is having a difficult time getting traction. Even the C++ Standard Library doesn't fit on many of the systems folks are working on, let alone the STL.
The system I'm working on at my day job has about 1meg of Flash and, IIRC, 128k RAM. It was reduced in resources to save cost (disposable device). The one I'm working on at home has about 4M Flash and 256k RAM. One of them is making liberal use of the STL and I know both have Python implementations available.
Tiny, memory constrained devices are still around, but they're a smaller and smaller part of the pie every year.
I specifically left embedded out because I didn't really want to make assumptions about CLR byte code running within the constraints of such environments. I've only ever programmed in C++ on embedded devices, so I can't actually comment on CLR (ergo the perhaps in my comment).
It is actually a pretty nice framework, but it does (did) require a 32bit CPU at minimum, and a hefty amount of flash.
That said, the UI framework was a joy to work with!
I should do some sort of write up of just .netMF, but I don't honestly recall too much about it in a general sense, since most of my time was spent in the weeds optimizing code.
I'm terrible at clickbait titles, so I sadly don't see much hope for future articles achieving any significant level of popularity!
Now we take multi-core, 64-bits, gigabyte address spaces, memory protection and multi-tasking Unix-like OSs for granted most of the time. Except for the most stringent requirements (such as hard real time or very constrained power budgets) that we find small bare metal platforms.
And those are real fun to do ( but not as much fun to debug).
If you really want to get a sense for how broad the APIs are today:
https://learn.microsoft.com/en-us/dotnet/api/system.numerics...
I've been working on a custom game engine in .NET for about a year now, and I still haven't had to pull down a 3rd party nuget.
It should provide up to 48x perf improvements as compared to .NET 7
I believe Vector4.Transform(Vector4, Matrix4x4) is my hottest path right now, but as I get into more complex scene graphs, Matrix4x4.Multiply(Matrix4x4, Matrix4x4) will likely pop into the profiler.
For `Matrix4x4.Multiply(Matrix4x4, Matrix4x4)` its a bit less at `10.04ns` to `8.38ns` (~17% faster)
The main improvements tracked by: * https://github.com/dotnet/perf-autofiling-issues/issues/1144... * https://github.com/dotnet/perf-autofiling-issues/issues/1148... * https://github.com/dotnet/perf-autofiling-issues/issues/1146...
There are some more cases to be improved. `Matrix4x4.Multiply` in particular I need to update to use a proper SIMD implementation rather than its current scalar implementation.
If you have any other core scenarios where it's important, let me know and I can try to focus on them sooner, rather than later ;)
I have no special requests at this time. I'll dig into the above issues and comment on GH as needed.
Also, there's a ton of world class third party tooling around .NET that really makes everything better. Shout-out to LINQPad for saving me literally 100s of hours on testing, queries and quick POCs.
In the modern ASP.NET Core, things are much better organized and documented. The framework has far less magic involved. No magically auto-generated repositories, no @Autowired magic, and far less use of annotations. Things just make more sense.
As for the language itself, C# is nicer in many regards. Even basic things like properties instead of hand-written or Lombok-generated getters and setters, or operator overloading where it makes sense, lead to clearer code.
Regarding IDEs: I hate Visual Studio, but JetBrains Rider is basically IntelliJ for C#.
Also, there are plenty of old, no longer working code samples on the internet for spring, but the official documentation is really great and should be preferred over some random blog that likely 6 years old already.
And can you show the nice official documentation? All my searches back then pointed me only at blogs and stuff. All of them full of outdated advice — for example, the version I started with was one of the first to change the default file extension for Freemarker from `.ftl` to `.ftlh` for some invalid reason, but none of the online blogs were updated for it, I found out after a few hours of trying out random things when I stumbled upon the change log for that release. (The reason was allegedly “security”, but what stops them from disabling the insecure features and keeping the extension?)
Another thing that was woefully under-documented was the default security thing, it also took me forever to figure out how to get a login page showing and working.
Loading all of VS2022 is not fun if you just need to turn an image file into a stream of base64.
It is very hard explaining to Java programmers why Java is so bad. Country of The Blind (https://en.wikipedia.org/wiki/The_Country_of_the_Blind) is very apropos.
C# is an incredible language that makes it easy to express a multitude of ideas from a wide range of programming paradigms.
Referencing a short story doesn't really explain it to anyone.
Recently .NET has been very good, but whenever I program in it now and then there are things I miss badly from the Java side.
From what experience I've had, C# is a very ergonomic language, with good balance between an expressive static type system and do-whatever-when-needed dynamic features.
Another language I'm looking at is TypeScript, since everything's in browser anyway, and browsers got fast.
Guess I just like Anders Hejlsberg.
I'm not sure there's anything as powerful as Pandas + Numpy + Matplotlib in C# (or almost any other language, for that matter), but it looks like there are a few attempts.
Microsoft.Data.Analysis: https://learn.microsoft.com/en-us/dotnet/api/microsoft.data....
SciSharp: https://scisharp.github.io/SciSharp/
ScottPlot: https://github.com/ScottPlot/ScottPlot
Plotly.NET: https://github.com/plotly/Plotly.NET/
This for for sure not. They do not have capable multi-platform UI.
What put me off was how cumbersome it seemed to be. Maybe I’ve just been spoiled by JS/TS, but where are the following features (which I believe to be quite basic)? - Union types - Object literals - Functions as first class citizens
I get that C# is supposed to be a purely OO language, but in this day, the most useful languages are multi-paradigm.
People like to dish on JS/TS but IMHO one reason why they became so popular is overlooked. There’s just something so direct and unceremonious about programming in JS, and with TS you get strong expressiveness as well.
Until and unless the .NET languages have that it will be hard to pull me away.
Object literals are a thing, they’re called anonymous types. You just new them up. And functions can be passed around as first class objects, with some minor type boilerplate in a few places.
There are a few places where you have to adjust to different naming conventions and types are obviously stricter but my experience is that for the most part modern c# has all the things I like about TS/JS.
Yes, these are missing in C#.
> Object literals
You could use records[1], or anonymous types[2].
> Functions as first class citizens
There's delegates[3] and lambda expressions[4]. Is there anything that's missing here that you need?
You can use lambda expressions almost exactly like you might in JS/TS, even omitting the type:
And if you want even more functional, you could always use F#.[1]: https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
[2]: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals...
[3]: https://learn.microsoft.com/en-us/dotnet/api/system?view=net...
[4]: https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
Not quite with directness of JS.
> There's delegates[3] and lambda expressions[4].
Again you can get something equivalent, but not without some ceremony. It’s not as frictionless as with JS.
I'm not sure how much less friction you want than directly declaring lambdas, or LINQ, or any of the newer functional constructs.
Like I said, if you want more functional, there's F#, which is a dialect of ML.
.NET in general has great support for 64-bit platforms and while it wasn't the default target for .NET Framework, it has been the default target for .NET [Core] for years.
We notably don't support single-dimensional arrays that have a 64-bit length or individual objects in general being that large. However, that also isn't necessarily a bad thing as there is a large difference between your overall application supporting more than 32-bits of memory (decently common and generally good) and individual allocations using more than 32-bits of memory (not so common and generally not good to have).
If you're creating individual allocations that are larger than 4GB, you're likely not correctly accounting for devices that only have 4-8GB of memory, are more prone to cause memory thrashing, and may end up negatively impacting other parts of the system since such allocations place special restrictions on how the GC can/should interact with the data or in the case of data that is or contains reference types it can add large numbers of additional references for the GC to track.
For such scenarios, it's often better to manage your memory differently, to support streaming/buffering where possible, and if it is the rare scenario that actually necessitates such large allocations to use things like NativeMemory to bypass the GC alongside Span or the SequenceReader/Writer APIs to work with smaller chunks of data. This also allows the data to be thought about differently since the algorithm you'd use to work with small to medium sized data is not necessarily the same algorithm you'd want to use when working with large to huge data. The time cost required to process multiple GB of memory is significantly different after all, as is the cache locality and other aspects.
At this point even my phone has 12GB of memory. Although I am more concerned about deep learning. Streaming tensors doesn't make much sense.
The other annoying bit is memory-mapped files.
That being said, it is largely in the same boat where if you're working with more than 2GB of memory in a single allocation, you're not necessarily going to have a good time. Even if your phone has 12GB of memory, you in practice get a much smaller portion of that available for actual usage and you don't want to cap out the available RAM either since that will cause thrashing and other issues.
75-80% of available physical RAM is about what you want to cap out at, and that's if you're the only app really using any resources.
MemoryMapped files notably support 64-bit values today and have since they were introduced. As have streams in general.
Streaming tensors can make sense and is necessary with extremely large models. The CPU cannot handle all data at once and the cost of loading everything from disk is often expensive, so you'll want to balance loading in data you need in the short term with data that isn't needed anymore or will only be needed in the long term.
Streaming or otherwise chunking your data can likewise help with parallelization and while there are some domains where chunking isn't possible, streaming always is. It just comes down to data size to determine if its beneficial or not.
https://www.wildernesslabs.co/
https://sandervandevelde.wordpress.com/2022/12/15/fun-with-n...
Plus many "embedded" scenarios have an OS capable of running regular .NET as well.
The problem of .NET versus other alternatives like Java (as an example), is the 2001 - 2014 legacy of being mostly Windows focused, which hinders the choice of libraries and tooling versus those alternatives.
For example, coming back to the embedded scenario, .NET has nothing comparable to PTC, Aicas or the endless variants of JVMs shipping on copiers, electricity meeters, M2M gateways and such.
After .NET Core I was one of the people that really thought "maybe Microsoft has changed at least in the .NET division, let's not be prejudiced, if they want to make FOSS let's give it a try". But of course they showed their hand and I'd have to be a fool to believe this is a platform worth investing myself in.
It's even killed my enthusiasm with F#, despite it almost growing into its own thing after how much MS has neglected it.
That can't be the case?
Luckily, there are various third-party debuggers available. E.g. from Samsung (MIT licensed) and Jetbrains (proprietary for their IDEs).
https://github.com/Samsung/netcoredbg
As the link notes, there is Samsung's open source debugger, but it's not the one that is used by any of the common IDEs (VSCode, Visual Studio, or Rider).
It's certainly not an amazing situation that I want to be defending, but most people look past the fact that they're running plenty of proprietary stuff inside their VSCode editor and if you're looking past proprietary extensions for JS or Python, it makes sense to also look past proprietary extensions for C#.
The perfect example of why Microsoft can't be trusted. VSCode had a great open source Python extension which everyone used. Then Microsoft hired the developer and switched to recommending their closed source extension instead. VSCode extensions are then licensed so they cannot be used with VSCode forks. It really shows Microsoft's mindset.
Man, people are entitled and just want free labor…
Does it get close enough for jazz for the businesses who use it? Yes.
In the end that's who .NET seems to actually be for, that's who mostly use it. For those of us in that situation, it's a pretty damn good choice.
- the ability for the open-source extension to, at the user's option, additionally interface with existing closed-source tools (in a non-license-affecting way), was added
- they wanted to limit hot-reload in .NET 6 because of quality issues (but reverted after people disagreed)
- Microsoft's debugger isn't open-source (even though there still is a popular open-source one)
- a clerical error resulted in all the repos the .NET foundation were administrating getting moved to the .NET foundation's GitHub, including ones that weren't supposed to (which, being incredibly obviously a mistake, was instantly reverted)
If you call these things 'showing their hand', I would call that motivated reasoning. I consider it impressive that a site dedicated to collating all the idiotic drama in order to smear the participants, can only find four examples, despite targeting literally Microsoft. By comparison if you started trying to collate the community drama for Rust or Golang (or god forbid Java) you'd be at it all day.
Please stop linking this website.
- they wanted to disadvantage open source users because of their proprietary solution
- they gatekeep the debugger while pretending it's an open source ecosystem
- several "clerical errors" demonstrating a pattern of undermining an open ecosystem
Yes, except for your charitable wording of a company's hostile "interpretation" of an open community, those are the reasons why it should be avoided.
It was not a clerical error. E.g. nobody typed wrong command or something. That was a decision .NET Foundation heads made and executed. AFAIR https://github.com/clairernovotny
> was instantly reverted
No, it was not instantly reverted. Took us over 1 month to get our repository back under our full and undivided control.
https://dotnet.microsoft.com/en-us/platform/support/policy/d...
We've still got code running on .NET Framework 4.8 (supported, I think?)
We've still got code running on .Net Core 3.1 (now out of support)
We are moving to .NET 6, but given our own 6 month release cycles, and layoffs, I'm not sure we can keep up.
just gift me swift + vim + linux for webdev please! no xcode and no visual studio.
Can you elaborate on this? I develop Web API's on Linux using Rider and deploy on AWS, I never felt any pain.
What kind of project? GUI? Web? Infrastructure?
And what was the experience of the team with .NET when you were urged to use .NET 6?
I've done multiple Framework 4.8 to .NET 6 migrations and the issue is almost always compatibility with new libraries. Language issues rarely if ever come into play.
What C# language version were you working with before?
We mention in our job descriptions clearly .NET 4.8 and still get 100s of applications. In the meantime we are working on upgrade to the new .NET but it will take at least couple years.
Those are C# language features, not necessarily .NET 6 features:
• https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
• https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...
"global using" is a code readability regression, so I wish it had not been added and I'd recommend against using it.
As a counterpoint: it's handy for Unit Test projects where you always want to import the test framework.
From a quick glance internally, the overwhelming majority of repos are using an antiquated build/packager that while it might have been useful a decade ago is a productivity killer today.
The newer build / package system used publicly is light years ahead and provides a boon in productivity.
Not really sure why so many services in MSFT still run .NetFramework when “just” migrating over can lead to sometimes order of magnitude increase runtime performance and decreased resource consumption.
I think one of the real reasons is internally, most of the leads aren’t aware of it. There should be more evangelizing of the .NET team across the different orgs
We work super closely with teams and often post about their fine work and even finer results on our blog.
https://devblogs.microsoft.com/dotnet/category/developer-sto...
Shameless plug, but I've tried to cover a lot of this here:
https://dusted.codes/dotnet-basics
There's no learning curve.
There's a lot you can do with C# with .NET, game engines, cross-platform tools and so on.
I develop on a Mac (JetBrains Rider) and deploy to Ubuntu. .NET is truly cross-platform at this point.
The EF Core + ASP.NET Core combination is very addictive.
I can support millions of DAUs with a 3-node K8s cluster running .NET7 instead of a 50+ node cluster with Python or node. Just simpler, without npm package dependency hell, and produces a nice clean single file executable.
Quite frankly, they seem to be roughly equivalent in everything, from features to developer experience to performance. We ended up preferring Flyway for db migrations for both platforms.
I didn't really encounter any issues when moving from 4.8 to Core 1.1 then 3.1 then 6. There were a few cases where a library wasn't available the first few days but that was mainly during the 4.8 transition. After that, most libraries migrated to using .NET Standard.
Probably the only gotcha when moving cross-platform was platform specific code. In my case, I had some very minor code to resize a console window when run interactively that was exploding.
Overall, I can't speak for the desktop story but services, command-line apps and web-apps were literally copy/paste binary to run or git clone and open in Rider to edit.
.NET Framework (v1.0-4.8) - 4.8 Currently still supported, but don't build anything new in it. It only gets very minor updates. Not cross platform (Mono can help, but euuughhh), slower, stuck with C# 7.3.
.NET Core (v1.0-3.1) - Out of support, transition period between .NET Framework and modern .NET. Cross platform support, some support for AOT compile.
.NET (v6-8) - LTS every other version starting with 6, 36 months LTS, cross platform, magnitudes faster than .NET Framework. Successor to Framework and Core. Many features of .NET Framework have been abstracted to NuGet packages.
.NET Standard (v1.0-2.1) - Interop API specification for Framework/Core/.NET. Write a class library that targets .NET Standard and you can use it in more than one runtime. You'll see a lot of NuGet packages target Standard. If you're writing a class library you should probably target Standard.
"Core" products/packages - Many packages/libraries have been renamed to include "Core" in the title. ASP.NET Core, Entity Framework Core, etc. These are libraries/packages that only have implement their core functionality. For example, ASP.NET Core has some basic implementations, but does not include things like Web API, MVC, Authorization, Razor. If you build an ASP.NET Core project you'll be pulling in a lot of packages based on your needs. The features/libraries are more atomic and less reliant on a full version update of ASP.NET Core.
1. guaranteed type safety;
2. blazor, so no more backend/frontend, js.
3. vast standard lib, so less dependencies;
Reservations I have would be that:
1. it's owned by microsoft and I'd be running on linux, so isn't it a bit of a mouse-toying-with-a-cat type of a situation?
2. libs may be aimed at enterprise - will need to provide lots of boilerplate to get minimal functionality?
1. Microsoft is a pretty big contributor to Linux at this point. Their cloud arm pretty much forced their hand and I don't see that story changing anytime soon. .NET on Linux has been great in my experience.
2. Some libs are, others are decidedly _not_ enterprise driven. The ecosystem is pretty large so there tends to be a lot of options with most packages. Just take a look here, https://github.com/thangchung/awesome-dotnet-core, the ORM section has things as big as nhibernate, which is about as heavy-handed as it gets, to things like Dapper which is about as lightweight as you can get.
Update to the .NET language strategy - https://news.ycombinator.com/item?id=34690969 - Feb 2023 (145 comments)