Actually, it's a very good language (although arguably getting too featureful/complex for its own good these days) with fairly suboptimal tooling. NuGet is slow and a pain in the neck, MSBuild is a huge, slow, blundering XML-tastic beast of a thing, etc.
Migrating large projects to dot net core piece by piece is fraught with tooling bugs and issues (you pretty much need to migrate everything to SDK-style projects before you do anything else, for example, otherwise you get strange interactions between net461 and netstandard projects around auto-generated binding redirects). There's still DLL hell. Default "copy local" results in crazy n log n file copies in large solutions that totally kills build performance (you can tweak this to use hard links in an effort to improve things, but not within Visual Studio which is where I really want cycle times to be low, or do mad hacks with shared output folders, but that can give you nondeterministic builds).
So it's far from all roses - check out their bug trackers on github and there are a number of surprising issues. There are also a lot of missing things on Linux still (e.g. Out-of-the-box support for kerberos auth in ASP.NET core/WebAPI things on Linux). Quite a number of APIs pretend they are there in netstandard but throw at runtime on Linux machines, and yet other things are annoyingly half-hearted, like mapping some Linux syscall return codes to Windows HResults, but not all of them and not consistently across all APIs.
It's getting there, but the surrounding ecosystem has a lot of catching up to do compared to Java, IMO.
C# tooling is very sub-par compared to what exists in the Java world, and I'm not just talking about build tooling (package management is a tough problem and Maven/Gradle are not perfect but NuGet is just atrocious) but debugging/deployment tooling as well. It's an artifact of how C# was a closed-source product for so long, the first-party tooling is pretty good for basic stuff but try deploying it outside a Windows environment and the edges become viciously sharp. Mono is a joke compared to OpenJDK, and I can happily deploy my application on any of a half dozen web servers that provide some superset of capabilities of the official server.
I understand that's changing of course, now that Microsoft has open-sourced the core of the language and started pushing to get support onto Linux and other platforms, but they are still making up an almost 2-decade deficit here.
But yeah, Visual Studio beats the pants off Netbeans and Eclipse, while functional, is very clearly what happens when you let an engineer design a UI, everything is possible and nothing is easy.
No, they are correct, the tooling is bad. Tooling in the sense of setting up a build for a large and complex project, that can resolve dependencies quickly and correctly, where the build is very fast and deterministic, where incremental builds always work correctly, where building multiple configurations is easy and reliable, and so on.
I believe the state of the art is bazel and similar systems. Bazel supports C++, Python, Java, and Go well that I know of, maybe more too. It's also extensible, and people have rolled their own support for various languages. You can find some custom bazel rules on GitHub.
Bazel is an interesting build system, but it worries me that there are TensorFlow releases from 2018 that won't compile with Bazel clients from 2019 without adding extra flags.
The development tooling is great for small projects and breaks down a little as project size grows, while the automation and deployment tooling is middling-to-bad in my experience. The parent post is right about NuGet and MSBuild both being pretty ponderous compared to the myriad of package management and build solutions for various frameworks in the OSS world, and deployment for wider-scale systems is falling behind the K8s/containerized state of the art as well.
"Comprehensive" is not always a positive trait of an IDE. I much prefer Rider over Visual Studio.
NuGet does have some rough edges, and compile time for even my small .NET Core projects tends to be on the order of seconds, which is surprising for a mature compiler and stripped-down framework.
If they're Web projects and you have node_modules (or a similar huge number of files) in a subfolder, you may need to exclude them in your project configuration. I've found dotnet core builds to be very fast, unless the build is accidently scanning a few hundred thousand files it doesn't need to. Example at very top: https://github.com/caseymarquis/QApp/blob/master/App/App.csp...
I tend to take the a .gitignore for C# and merge the Node baseline together, add in test* and .* roughly speaking [1]
For that matter, anything using node/npm on anything but SSD/NVME is VERY slow (HDD, even enterprise drives)... local builds for me are in a couple seconds for a large complex project, on the servers it's minutes. So, YMMV.
The API layer I'm working against is .Net core, local build is under 3 seconds, building/deploying 12 seconds on my desktop (kills existing container, builds in one container, deploys to another and starts) docker for Mac, probably faster on linux... NVME drive on i7-4790K, 32GB RAM.
I don’t think it’s the compiler actually. I’m more inclined to blame the project system. In fact visual studios does some hacks just to get around it in some perofrmace sensitive things.
Indeed. It's actually pretty easy to write a custom msbuild logger to instrument (and subsequently chart) all the steps and you discover most of the wall clock time on big solutions with large numbers of projects is not actually compile time. csc itself is fairly competitive with javac. But by Christ, msbuild and nuget restore (which needs to run masses of msbuild machinery these days) are slow.
It's definitely the project system. I once worked on a solution containing ~150 projects. I consolidated all the code down to about 15 projects and the build time of the solution dropped by about 5x. I've been working in Java lately and frankly, I see little difference in compilation speeds between the two.
I find VS to be a bloated legacy relic that's particularly limited without ReSharper, although I much prefer the leaner and more advanced Rider which is a fraction of the size with more intelligent features that VS has been copying (from R#/Rider) for several years. Rider is leaner, faster, smarter, more extensible with higher quality plugins offering better support for developing modern Web Apps.
IMO the investment in VS Code basically signals VS has become too bloated and complex to innovate on so they're better off creating a new IDE from scratch with better plugin extensibility and ecosystem that's innovating and delivering features significantly faster than VS which comparatively looks like it's stalled.
I don't know why you appear to have been downvoted - that's pretty much bang on IMO. Rider loads very large solutions an order of magnitude faster than Visual Studio and is generally more stable too. I've built tooling to do very large scale refactors at work and VS won't even open many of the synthetic solutions I generate as part of that as they seem to be just too large for it, whereas Rider always gets there eventually.
I haven't really used R# or Rider so cannot comment there. Will say I love VS Code and the progress it's made. Though once they had a file tree and an integrated terminal (bash on win/lin/mac) I've been very happy.
It all depends on your perspective. Java has a very long history of enterprise-grade tooling, including IDEs. Way back when VS still didn't have all the basic refactorings for C#, IDEA had structural search (i.e. pattern matching search that understands language constructs, types etc). VS has improved, but so did the Java IDEs.
So when you look at VS from the perspective of someone who's used to typical Unix or JS tooling, it's comprehensive. If you look it from the perspective of an old time Java developer, it's lagging behind.
Back when ReSharper was first released, it basically advanced VS to the point that was considered essential baseline by most Java developers.
As I recall, at the time, it seems that the Java ecosystem was mostly investing into writing code and declarative markup (usually XML), while Microsoft was most interested in visual designers and other ways to help devs on its platform avoid writing code. Thus, VS was far easier to get started with, but advanced coding was much better in Java IDEs.
It's funny, post 9-11 I was pretty down and out for a year or so post-dot-com etc. I learned C# using the command line compiler and the complete reference book in 2001-2002. No IDE at all, and building with BAT/CMD files.
I don't think the tooling caught up to the ease of not using the built in tooling until VS 2005 for me. Of course by VS2012, it felt like such a bloated slow mess, I don't think I've looked back much until relatively recently. Been doing a lot of Node work, which I tend to think of as very low friction.
These days, I absolutely love VS Code which tends to strike the balance of more than an editor, but not slow and bloated like a typical IDE. Integrated file tree + terminal are the best UX to me.
I've not used C# and .Net Core in any real capacity so thank you for the corrective comment. I think some newer languages are getting tooling right, like rust and to some extent go (though dependency handling has been a sore thumb).
Maybe C# is really only fantastic on Windows with Visual Studio?
Even on Windows I find msbuild to be a huge drag, especially on larger projects and at scale in an enterprise. There are also some questionable design choices for things like nuget behaviour around dependency versions. For example Version="2.0.0" really means "version 2.0.0 or above", including major version updates (which you probably actually don't want by default if people are following semver). Despite that, if your project A depends on library X with Version="1.0.0" and A also depends on project B, which itself depends on library X at version 2, you will get a build warning (or error, if you do warnings as errors, which you should) that A is downgrading the version. And it does (you'll get version 1 in the output folder if it's a warning). Which is arguably wrong. (If I'd specified "[1.0]" as an exact match, I'd expect that.) It's doubtless done in the name of backwards compatibility, but stuff like this still sucks, even if there's a reasonably good reason for it having to.
Would you mind sharing how to fix build performance using hard links? Is that similar to setting all projects' output dir to the same physical directory?
Like I say, you can't do this from Visual Studio as the common/csharp targets files have specific checks that stop it working, but if you're just invoking msbuild on the command line then you can set the following properties:
It will give you a considerable speed-up for very large solutions, especially if there are lots of common project dependencies, as it will make hard links instead of copying entire files. This could save you gigabytes of file copying in very large solutions. Google for "hard link" if you don't get what I mean by that.
Note that dotnet core works differently and doesn't do copy local at every stage up the dependency tree when you build, instead copying dependencies directly into your top level application project only when you run the publish target, which is obviously cheaper than either approach.
Also, setting all projects' output folders to the same directory is a pretty bad idea. You're presumably doing parallel builds (/m). If so, and two projects depend on the same library but at different versions, which version will go into your output folder? Depends which project happens to finish building last. That's non-deterministic. Boo. What if the versions aren't even API-compatible? (e.g. Some of your test projects are still on NUnit 2?)
Using hard links gives you most of the speed up, but without the attendant issues.
Migrating large projects to dot net core piece by piece is fraught with tooling bugs and issues (you pretty much need to migrate everything to SDK-style projects before you do anything else, for example, otherwise you get strange interactions between net461 and netstandard projects around auto-generated binding redirects). There's still DLL hell. Default "copy local" results in crazy n log n file copies in large solutions that totally kills build performance (you can tweak this to use hard links in an effort to improve things, but not within Visual Studio which is where I really want cycle times to be low, or do mad hacks with shared output folders, but that can give you nondeterministic builds).
So it's far from all roses - check out their bug trackers on github and there are a number of surprising issues. There are also a lot of missing things on Linux still (e.g. Out-of-the-box support for kerberos auth in ASP.NET core/WebAPI things on Linux). Quite a number of APIs pretend they are there in netstandard but throw at runtime on Linux machines, and yet other things are annoyingly half-hearted, like mapping some Linux syscall return codes to Windows HResults, but not all of them and not consistently across all APIs.
It's getting there, but the surrounding ecosystem has a lot of catching up to do compared to Java, IMO.
The language is nice, though. F# also.