Welcome to C# 9.0
devblogs.microsoft.com
devblogs.microsoft.com
I left .NET land at 6.0 and .NET 4.x versions mostly because of Windows eco-system (small open source community, almost no alternatives to out of the MS things, bad linux support). Since that I've been working with Java, Swift,JS, Python, Golang and I still think that C# is one of the best-designed languages. Very few of them keep evolving through the decades, hopefully it can become the language of the year at some point, always liked to see how new features got implemented under the hood and what kind of features get into next release.
Well done C# team
It's amazing how the language advances over years
As an example, during this time the development community figured out that using immutability as the default brings benefits.
Kotlin is designed with this in mind, but C# isn't - e.g. C# has this cool feature for object initialization which is so handy and all developers use it. Except for - it doesn't work with immutable classes (the ones with readonly fields). As an effect developers dislike to use immutable classes since it's not ergonomic in C# and instead use standard POCO.
Another example is that C# still in this age does not support readonly parameters and local variables (which even Java and JavaScript (!) support). In Kotlin "readonly" local variables is the idiomatic code practice which doesn't make code any more verbose. And in the case they decide to add it to C#, it will have to be at the cost of verbosity (similarly to how Java does it) because of backwards compatibility.
Well good thing they're adding that in C# 9 then
Still, they are playing catch-up here.
So from that perspective, Kotlin is playing catch-up.
There is also detekt but it's true it is inferior to solution that Java has. https://github.com/detekt/detekt
PMD is targeting kotlin initial support for their next major release https://github.com/pmd/pmd/issues/419
I've answered a jetbrains survey recently and they revealed they are working on a new product that would be a full fledged static analyser, maybe this would solve the issue?
Code examples have a lot of what looks like lambda callback hell and I find it hard to read but again, I might just need more practice.
I hope for C#'s sake that at some point it can metamorphize--not just evolve--into a new language that can leave some of the crufty decisions behind.
That's being a little too harsh, in my opinion. Even if you were designing both kinds of nullable types right now, it'd be difficult to have them behave the same way without adding runtime support for keeping track of nullability of reference types. And that's quite a big task.
To me, VS 2019 refactoring suggestions and Roslynator extensions helped a lot to learn and use new syntax capabilities and idioms: you write code in "the same old way" and then often roslyn is able to convert this code using new features, often in a concise, readable but undebuggable way :)
Perhaps it's gotten better - TBH I haven't checked in years - but it used to be a horrible bug ridden mess for doing things aimed at Linux (i.e. via mono).
Even the newly announced MAUI is only "community supported" on linux.
It's just a process that picks zip files from the local SFTP service, sends each entry in the zip to an external web service, and writes the result of the file to a new zip in the SFTP directory. Extremely simple, but also the kind of application in which resource leaks become apparent very fast, and it's been far more stable than anything we had on Windows where we had to reboot servers once a month just as a precaution.
A few years ago I was playing with Kotlin when it had been recently released, and I remember thinking that eventually it would be a likely candidate as a default language for new enterprise projects. My reasoning was based mostly on it being a better Java, it solved just the right problems but wasn't too different and thus easy to learn. And at the time the JVM had too many advantages over .NET (multi plataform, open source, supported every technology under the sun)
Fast forward a few years, and .net now supports Linux natively, and is even faster on Linux than Windows. Microsoft has or is open sourcing pretty much everything, and with the rise of Nuget the third party library ecosystem has grown by leaps and bounds. C# has become an amazing language, considering that back in 2000 it was basically Java. While Oracle has regressed and is oppressing the ecosystem in its typical ways.
Even though I still like Kotlin better (purely from a language design standpoint), C# has evolved so much it nearly matches it, while Java is just a kitchen sink of non-cohesive features and libraries. C# in 2020 almost seems as it was designed from the ground up to be a semi-functional asynchronous OOP language with reifed generics, linq, async / await, null safety, and many more features.
That is absolutely mind boggling, because it is a language that made nearly all the mistakes that the originally Java did back in the days (save checked exceptions), and now a days I think it should pretty much be the default plataform for any app that needs to interact with enterprise technologies, and should honestly be considered in all green field projects if the team has development expertise in it. We've stopped being a mix shop and are now pretty much .net exclusively.
Not sure what you're referring to here. Java/JVM has been open sourced for a while as well.
> while Java is just a kitchen sink of non-cohesive features and libraries
I disagree. If you look at the new features coming out (pattern matching, records, green threads/fibers, value types, etc.) the Java designers are taking a very principled approach. Everything fits very well with the language design.
Right now there is Xamarin Forms which has a community maintained Linux layer.
You can use that today if you write a Xamarin forms app.
From the Microsoft side of things, no, you can't just write a winforms app and use it in Linux.
However, they have announced MAUI which basically lets you write XML/XAML UI Declarations that are platform agnostic and can be translated into the various layers (such as Xamarin Forms.) I believe that's supposed to be a thing sometime late this year or early next (don't quote me on that!)
Other projects to look into are AvaloniaUI and Uno. Those are community projects that try to give you cross platform UI today.
As an aside, although common, I dislike the term "poaching" when it comes to hiring. It's negative connotations are inescapable, but also inappropriate when talking about hiring.
I think C# was an attempt to design MS Java which is better than Java
The only thing I don't miss is the lack of community. Many things you can get for free in Java/Python cost money in Microsoft land. Even common stuff like decent excel and PDF support. Its getting better but was still the case last time I looked.
What C# needs is Java interop. The VM and bytecode structures are similar enough for it to work. There was a guy maintaining a library for this until recently :(
Official CLR Java interop would kill Java. Within a few years every new project would be in C#.
The only other places I'm aware Java has a big advantage is GC and monitoring. C#'s GC is old school, has long pause times. Makes C# a no-go for many uses. Java also has better monitoring and profiling support.
There -are- still a couple sore points, PDF comes to mind. But there are at least a couple different good projects out there for working with Excel at this point.
Bigger problem is a larger portion of C# developers and their managers are frightened of shifting away from the Microsoft blessed stack. That's what creates this chicken-egg situation where good projects don't have enough community behind them because there aren't enough people using them.
GC in C# isn't perfect but works fairly well if you understand it. There's plenty of ways to write minimal or zero-allocation code and it's gotten a lot easier with the newer Span types.
Monitoring though... yeah The first time I learned about Blackbox and the like I got a bit jealous :)
Now developing in Python at work, I can find a multitude of packages for every need I have to meet, which is perfect for productivity, but I feel I can never understand the language enough because all I do is to import some packages and get work done.
I really hope C# gets more popular among devs. Where I live only large non-tech companies use it internally, which might explain why there are not many open source libraries in C# compared to other languages.
Though, with all the comments here saying C# is turning into F#, I'm tempted to try out F# as my first functional programming language now.
I think that with the latest improvements (from v7 to now) Microsoft is trying to "fill the gap" between F# and C#, and let C# developers embrace functional paradigms (at least, some of) without switching to F# itself.
C# designers: "Hey, nice language features you have there. I'll just borrow them for a bit ok, it'll be fine..."
Later, C# programmers: "why would I learn F#, C# does all the same stuff!" (even though it doesn't)
Edit: I admit being both glad that C# is gradually migrating to the ML-style coding which will make F# more mainstream, and nervous that C# will get close enough to kill F# adoption yet too far away to actually get all the benefits of F#.
Some examples of this include the Hindley-Milner type system, partial application, discriminated unions, and all of the compile-time goodness the F# compiler gives and the C# compiler ignores.
As a member of the F# Evangelism Strike Force (to use an n-gate ism), I want to argue this point but there is not enough info to determine what 'enough momentum' means.
I can produce, without leaving F#: libraries, cli apps, windows services, windows desktop apps, websites (asp.net core + giraffe), web apps, SPAs (SAFE stack), and more. If I target .NET Core, I can run my F# in windows land, linux land, and anywhere else .net core has been ported. What features does C# offer that F# doesn't, aside from being more familiar to lots of MS devs? Even I started my dev journey with C# on Windows Mobile 5 via .Net Compact Framework.
Cons: The F# tooling is just worse than C# tooling. Compare the 20-year old language with support since Visual Studio 2003 .NET to the one that has for some reason focused on the VSCode + Ionide plugins rather than the tooling that VS users run into and even I can't really argue that C# has better tooling. Biggest weakness of F# is all the wonkiness when it comes to common tasks like making, running, building, publishing codebases. The use case of something common like 'make me a new blank app, I want it to use paket for dependencies and to spit out an alpine docker image with .net core sdk at the end' should be 1 command, then triggerable from the VS Debug/F5 button. It just isn't that yet.
> C# has to grow somewhere why not this direction
I'd rather C# lean more FP than lean more OOP, sure, but _does_ C# have to grow somewhere? Can't a language spec be declared good enough / maintenance mode at some point so the programmers can focus their learnings on fuller understanding of the spec itself, as well as improving the implementations and tooling around a language?
IMHO my biggest issue with languages like F# and Haskell is like you mentioned the lack of tooling. I can even get over the fact that the ecosystem is smaller but the lack of ergonomics (things are harder to do, there's more friction in the dev process) always sends me back to C#. I wish F# tried to get into Roslyn instead of having their own compiler. I get the prestige and practicality of doing your own thing but I think it costed them a lot of missed out features and polish. I'm not that familiar with F#. It very well could be the language is too different to reuse almost anything from the semantic part of Roslyn but there's still so much else there they could get for free
Partial application can be one of those write-only code constructs unless used in very simple/canonical patterns. I'd also like to have a Scala like "hole" syntax with positional args -- this is also need to alleviate the need to write a (fun -> ...) when calling methods on object in a |> pipeline. And speaking of pipeline, they look nice, until you want to debug through them. (Need something like Ozcode's LINQ debugger for pipelines.)
F# also (last I checked) doesn't do the level of optimizations I'd like to see, such as removal of tuple creation between fn's when there never actually stored, etc.
Although I understand the rational for the Curried form for fn types, it seems a bit pedantic to present things this way by default -- seeing (int -> string) -> Foo -> (bar list -> baz -> qux) is IMHO harder to look at than the standard presentation. Although C# really needs seq and post-fix types -- "IEnumerable<Foo>" is an eye-sore compared to "Foo seq".
But it's hard to go back to any lang w/o DU's...
Put another way: if I'm going to use these features anyway (hint: now that they're in C#, I am) why wouldn't I do it in the language designed around them, rather than the one where they are bolted on?
When C# didn't have these features, there was ironically more reason to use C# because then these idioms could be argued to not be accepted by the community to the same degree.
In a few years, C# 20.0 will have only one release note: Changed the name from C# to F#
Just look at plumbing with init, data records and with. That is what a case class with val properties in Scala gives.
But congratulations to the team on shipping v9.
Thankfully that problem doesn't exist with C# /s
For a mid-sized web service (tens of thousands of LOC), a clean compile might take ~30-40 seconds, but you rarely do those. Incremental compiles take more like single-digit seconds, and for most projects you can have a solid “compile on save” type setup that makes it pretty unnoticeable. And sbt itself, which used to be very slow to startup (sometimes 10-20 seconds), now starts up in a couple seconds.
It’s not lightning fast like Go, but it’s way faster than it used to be. Not much of a pain point anymore unless you’re dealing with truly huge projects.
It isn't. Pretty much every release (including C# 9.0) adds some features that make your code more concise.
I think it's broader than C# -> F# though. Java also has closures and higher-order functions, and in many debates on this forum it seems like OOP proponents aren't aware that these features are grafts from functional programming. OOP programmers also seem to have (finally) come around to the consensus that composition is preferable to inheritance.
So if there is a long con, I think it is about turning OOP programmers into ML or functional programmers. :p
class Foo(b: Bar) : Bar by bThe delegation is better than inheritance because you don't get all the methods from the base class if you don't need them.
At my company, we have banned it, because if you add a method to Bar the method is automatically added to Foo which makes the delegation as fragile as the inheritance.
Delegation does not remove the need for interfaces.
Except that Smalltalk -for which the term "object oriented" was invented - had them.
> Point p = new (3, 5);
At first glance, not impressive, since you could just do:
> var p = new Point(3,5);
However, it would clean up code like:
> graphics.DrawRectangle(RedBrush, new(3, 5, 2, 2))
> graphics.DrawRectangle(RedBrush, new Point(3, 5, 2, 2))
what's the advantage of the first example? i prefer the second, because i don't have to look at the definition of DrawRectangle in order to know that the second argument is a 'Point' object.
It's still nice to have the option in cases where it improves readability (maybe with named args or sth)
new List<KeyValuePair<string,int>> { new (“a”, 1), new (“b”, 2) }
versus having to barf out the type name for every element will be REALLY nice.
Saves some typing but it also has refactor implications too. If you change the parameter type, it would change the object being constructed.
var p = Point(3,5).
For cases like this it's no big deal, but deep/complex initalizers (like expression trees, etc.) look horrible in C# unless you create static helper fn's to init objects.
I spend so long at work when working on tests making stubs of objects with private setters etc (e.g. DTOs). That work is essentially gone now, awesome!
Relational/Logical patterns are going to revolutionize our ability to make high-level business logic even more accessible to non-wizards. The switch expressions introduced in 8.0 were already very nice for building out our complex in-line mapping code. This takes things to a completely different dimension.
I will say that I am a little confused on the role of Record vs Class vs Struct. Do we not already have the ability to declare immutable value types with structs? How does the Record improve on the struct which already exists in the language?
> Structs override this to have “value-based equality”, comparing each field of the struct by calling Equals on them recursively. Records do the same.
Seems like we might be splitting hairs here?
My understanding is that structs are not always a good choice depending on the size of the data contained within because they are put on the stack, so having an immutable class record does not necessarily overlap with the use cases for structs.
It seems like records are more of a syntactic sugar which gives you a number of pre-defined behaviours such as value comparison and immutability by default (vs. regular classes).
This probably an unpopular opinion but I wish they would make fewer changes to the language.
A codebase from C# 2 will look entirely different than something written in C# 9.
If you get a developer who has great experience writing 2.0 and bring him into a project in 9 it will look to him or her like a completely different language.
I pretty much wish they created a new .net language D#? (or just put all the effort into changing F# (which I also like).
I also do not like the terseness. Yes I get to type a few less charcters but it makes the language much harder to read:
Pretty much all examples here make some sense if you come from earlier versions or other classical languages including javascript
https://docs.microsoft.com/en-us/dotnet/csharp/language-refe...
https://devblogs.microsoft.com/dotnet/windows-forms-designer...
Sadly only in Visual Studio and not Visual Studio Code. And yes, there is probably no one who used winforms that wouldn't be shocked by WPFs steep learning curve.
I'm mostly developing server on linux so I'm not enough of designer to even begin to wrap my head around XAML / MVVM / WPF / UPF (?) new world order on windows.
SO glad they are going to allow for some simpler approaches - and no, I don't want to build skinnable apps for business - I actually LIKED that all the apps looked / worked basically the same in the old world even though that's no longer cool.
We now have some silverlight apps, some IE only apps, some WPF / UPF apps. But the old winforms apps still get lots of use and still work. I've found the "better" WPF / UPF stuff to kind of lag and stutter even sometimes - I've got no idea why. The winforms apps on new machines are snappy.
WPF is nice for fully customized UI where you want your application to look modern, but xaml can really be daunting. And it's not only xaml, but that whole MVVM thing can be a nightmare to teach and stick to in a large team and project. Moreover you probably need some designers or an external company to design your UI's to really shine.
I would keep a close eye on MAUI [1] and where it will go. The Model-View-Update (MVU) pattern looks interesting and the cross platform aspect could be really nice.
[1] https://devblogs.microsoft.com/dotnet/introducing-net-multi-...
if(foo != null) return foo;
Into return? foo;
It fits perfectly with the existing null coalescing operators and such, while really cleaning up a lot of code.If it returns null, what's the difference between:
>return foo;
and
>return? foo;
?
if(?foo){return null}
while (!return? foo) {
foo = get_foo();
}I'm not usually one for causal dismissals but that made me cringe. What on earth is the use case for getting rid of that tiny bit of boilerplate, relative to the complexity it adds to the language definition, that makes it worthwhile?
And I used to primarily work in scripting languages like Ruby where you'd get this 'feature' out of the box (although usually ended up writing a 'Program' class and a constructor/main method anyway for the scoping)
Can you open a text editor and get going with C#? Now you easily can. iPython and python notebooks gained lots of traction from just this type of simplicity.
If you were to write a "script" using the language, doing some things just top level is simple. Very pragmatic. I ALSO like that it's an error to call to any top level functions outside of this, so it keeps this from exploding complexity everywhere.
- declare a namespace for the file (no indentation)
- declare that the file is a class and can only contain one (top level) class (still no indentation)
- `using` statements that don't import every symbol into my namespace :
using System.Console;
...
Console.WriteLine();
instead of : using Sytem;
...
Console.WriteLine(); // where does "Console" come from ? god/IDE only knows
But yes, no to top-level programs.But alreay with these few changes, I've saved 10% of the 80 columns width. I've made it easy to read a file without an IDE. You can start to write actual code at indentation level 0. I've made it easy to have one class per file and hard to have two class per file, in the spirit of making good pratice easy and bad practice hard.
It doesn't solve the fundamental issue, but it definitely makes things clearer for me.
using Console = System.Console;Yes you can do `using Whatever = System.Console;`, fantastic, that's not the common idiom and it is harder to do (longer to write) than the usual idiom.
There are quite a few appealing things about the language, but I'm having trouble shaking the feeling that it's kind of like Java. I know both languages have evolved a lot, but some codebases might get stuck in some old patterns.
private string _typeName;
/// <summary>
/// Add new type name to the specified object for TypeNameSet.
/// </summary>
[Parameter(Mandatory = true, ParameterSetName = "TypeNameSet")]
[Parameter(ParameterSetName = "MemberSet")]
[Parameter(ParameterSetName = NotePropertySingleMemberSet)]
[Parameter(ParameterSetName = NotePropertyMultiMemberSet)]
[ValidateNotNullOrEmpty]
public string TypeName
{
set { _typeName = value; }
get { return _typeName; }
}
-- https://github.com/PowerShell/PowerShell/blob/15c2245af97486...Honestly it seems like just a lot of code and very little meaning. I can't help but think that there's a better way of expressing the solution.
I could have picked the wrong file, but I was poking around in lots of directories before I found any significant C# code at all. It seems like there's a whole 'nother level of boilerplate in the directory structure.
There's no logic there, this is basically just boilerplate for some other code to set properties on an object. Something that actually has some business logic will be much more interesting to read, eg.
https://github.com/PowerShell/PowerShell/blob/15c2245af97486...
I'm fine with verbosity. I'm fine with lots of data type declarations, annotations, things that make the compiler happy, etc.
But a file full of getters and setters? I can put up with it, but I don't understand why.
public string TypeName { get; set; }
not sure why it's not here, could just be older code. The [Parameter] etc stuff is all powershell-specific metadata that defines how to use it from the powershell language.
It would be nice to see if some other codebases managed to free themselves from some of this cruft and make something more approachable.
Add init to a property, make its class a data class, and boom you have immutable beautiful class. Kudos to these designers.
(This is similar to AutoValue in Java / data class in Kotlin, but it feels a lot more elegant and connected and simple than what these other languages offer)
Mono remains the best (only?) solution to call C# from C++ in a crossplatform way using embedding.
Mono as a project is a dead man walking. And honestly, that is good. Unity as the major other user is surely heading for .NET 5.
I would suggest to learn to embed .NET Core 3.1 and later .NET 5. Surely possible (see Unity, interop with WinRT etc, ..).
.NET 5 is MIT licensed and even gets attention for source focused builds (like needed by Linux distros). Redhat officially ships is own version. Summary: that is exactly not EEE.
var (f, l) = person;
is so much worse than
var (f, l) = (person.FirstName, person.LastName);
I don't want to have to refer to documentation or class implementation to understand what a destructuring expression does.
var (f, l) = person;
is gross and hard to understand. var (x, y) = point;
is simple and readable. var (first, last) = person;
didn't seem too bad to me. var (f, l) = SomeMethodReturningAPerson();
than: var person = SomeMethodReturningAPerson();
var (f, l) = (person.FirstName, person.LastName);
or: foreach(var (f, l) in enumerationOfPersons) { ... }
compared to: foreach(var person in enumerationOfPersons)
{
var (f, l) = (person.FirstName, person.LastName);
...
}
When you know what you want to compute, but have to throw in extra temporary variables it becomes tedious and error prone. Cut straight to the thing you want (the names themselves in this case), eliminate middlemen.foreach(var (f, l) in enumerationOfPersons) { ... }
tells him absolutely nothing about what's going or even that there are names involved
foreach(var (firstName, lastName) in enumerationOfPersons) { ... }
is better but doesn't give him an object to inspect to see where they come from and what else is available.
(the "Person" type would have to implement a "Deconstruct" method with two string out parameters, or alternatively someone could write an equivalent extension method)
Personally I think this is a better source: https://octoverse.github.com#top-languages
Or this: https://insights.stackoverflow.com/survey/2019#technology
But realistically if you're not doing .NET on windows, you're still an early adopter who's going to run into weird issues that you won't have to deal with on java.
.NET 5 is going to change this completely. .NET Core has already changed.
I love Kotlin and I don't really get a hankering for LINQ when I'm using it, but I wish people would stop trying to say "but we can do that too!" when they really can't.
LINQ brought System.Linq.Expressions and IQueryable to .NET which allows so much more than just filtering and grouping data. You can write entire data providers with LINQ and parse arbitrary expression trees in any way you like.
Entity Framework (Core) utilizes this very well. It doesn't just query an SQL database and then use LINQ's Where, Select etc. to manipulate the data but parses everything the developer has written to an expression tree and then generates an SQL statement at runtime.
Expression<Func<T>>As someone with background from Java but who has worked a lot with .Net Core lately, I guess it might depend on what part of .Net you talk about.
.Net Core worked extremely well on Linux for all use cases I saw, mostly web applications, cli tooling and batch/queue processing. I cannot remember a single case where we had actual problems because of Linux.
In fact, FWIW for small console applications it ran extremely much faster on Linux than on Windows, on the same hardware.
Another point where it is really hard to get people to actually understand the magnitude of the difference is in IDE support, what exists and what you get out of the box.
I mostly enjoy programming in .Net Core a lot but there are times when the difference becomes extremely visible.
Many big projects roll out drivers for the JVM (Java/Scala/Kotlin compatible), Python, and Go first. I agree that C# is a 'nicer language' than Java, but at this point, that doesn't make up for the lack of ecosystem.
What .NET still is not really good in, is first party apps. There is no Kafka or Kubernetes programmed in .NET.