
Welcome to C# 9.0 - azhenley
https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/
======
tarasmatsyk
I still think C# is one of, if not the best of designed languages exist. Even
it moves in much smaller steps than it was before I think it's for good.

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

~~~
eggsnbacon1
It really is wonderful. Used it at work years ago and still miss it dearly.

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.

~~~
Arainach
I wouldn't expect that to change any time soon. The Microsoft/Sun lawsuit
still stings inside the company and has legal impact decades later
([https://www.cnet.com/news/sun-microsoft-settle-java-
suit/](https://www.cnet.com/news/sun-microsoft-settle-java-suit/)). It's the
reason why, for instance, you can't download Windows 98 or Visual Studio 6 on
MSDN/Visual Studio subscriptions. Microsoft is now friendlier to open source
than it has been, but I would be shocked if they _ever_ got friendlier with
Java. (Disclaimer: I haven't worked at MS in several years)

~~~
zozbot234
And I'm sure that the Google/Oracle lawsuit hasn't exactly improved things,
either. Not to mention the recent licensing changes. Java is such a can of
worms legally that it's surprising that anyone sensible would want to touch it
with a ten-foot pole.

------
myu701
Look - I don't have anything deep to say here. I can only say that between
'records' and 'with-expressions' now in C#, I as a hobbyist F# developer feel
like I'm being shaken down by the mafia.

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.

~~~
kungato
Well F# obviosly never gained enough momentum and C# has to grow somewhere so
why not in this direction. All "big" languages are gaining more and more
functional and declarative features each version. I always remember this chat
by Simon PJ, the "father" of Haskell about convergence of languages in
features
[https://m.youtube.com/watch?v=iSmkqocn0oQ](https://m.youtube.com/watch?v=iSmkqocn0oQ)

~~~
myu701
> Well F# obviosly never gained enough momentum

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?

~~~
kungato
A language could be declaered good enough but none of the popular languages
are there. They all had plenty of "bad but popular" design decisions at the
beginning and now they are trying to compensate. What I hate is the constant
repeating of everything. I'd rather one language have everything crammed in
and we get to choose what we want and what we don't want. No "good" (my
opinion) language will ever have only "one way of doing things" so why not
just add everything and get over with it. In any case, all the "big" languages
seem to be racing to "add everything" anyways.

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

------
Parazitull
This seems similar to the joke where after Brexit, the Germans are angry that
english is still the official EU language and they change the english language
until it sounds a lot like german.

In a few years, C# 20.0 will have only one release note: Changed the name from
C# to F#

~~~
corysama
C# is Microsoft Research's 20-year-long con to turn Java programmers into
OCaml programmers so slowly that they don't notice.

~~~
throwaway894345
This made me chuckle.

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

~~~
thoraway1010
yeah for composition - I ALWAYS liked it much better!

~~~
snuxoll
Some languages even have syntax sugar for it built-in, _cough_ Kotlin _cough_

    
    
        class Foo(b: Bar) : Bar by b

~~~
_old_dude_
This is the most controversial feature of Kotlin.

The 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.

~~~
snuxoll
> 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.

------
tsomctl
Well, we're getting closer to F#. Still waiting on discriminated unions and
expression blocks. (Yes, I know, discriminated unions in F# are just
implemented in the class hierarchy. But it's awfully nice syntactic sugar.)

> 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))

~~~
woodrowbarlow
> 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.

~~~
maxton
The second argument is a Rectangle, which means you'd be repeating 'Rectangle'
twice in one line with the second style.

~~~
Infinitesimus
That's not obvious from the function name though. The function definition
could easily be `DrawRectangle(SolidColor, CornerRadii, Point)` and you
wouldn't know by seeing a bunch of `DrawRectangle(RedBrush, new(1,2,4,5),
Point(4,5,2,2))` would you?

It's still nice to have the option in cases where it improves readability
(maybe with named args or sth)

------
topkai22
I'm VERY excited for Record types. Automatically having automatically deep
equality in data types is going to really help maintainability- no more
"developer adds a field to the type but not to the equals function" type
errors.

------
benbristow
That "Init-only properties" feature is huge.

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!

~~~
0xcoffee
It also drove me mad with JSON deserialization. Hopefully this will work
nicely with newtonsoft.

~~~
jrimbault
I think they said it was only a compiler error, it's still a normal setter
underneath, so newtonsoft would not see any difference.

~~~
benbristow
Newtonsoft (and the new Microsoft .NET framework JSON (de)serializer) only
uses the setters once too to set the properties after processing the JSON, I
can't see it causing an issue.

------
bob1029
This is like reading through a list of Christmas presents I didn't even know I
wanted.

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?

~~~
OkGoDoIt
I’m also confused on the relationship between records and structs. I’m
guessing in practice it has some of the properties of classes and some of the
properties of structures, but I worry it’s just going to complicate things.
It’s not like all the old structs in the BCL will just go away.

~~~
mmcconnell1618
Wouldn't a Struct be passed by value and Record (as a class) be passed by
reference. Kind of strange to pair immutability with pass by reference.

------
ThinkBeat
I have worked with C# since the early beginning I have used it daily since
then. I do know the ins and outs of the different up until C# 8 (latest
released) and now .Net core. because I work with it every day.

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://docs.microsoft.com/en-us/dotnet/csharp/language-
reference/keywords/switch)

~~~
oaiey
I would not want to miss the many things in between. My argument is more: I am
extremely happy I am bound to a language which actively evolves, taking me
along the ride.

------
thoraway1010
What is the winforms simple (ie, drag and drop form designer, click through
for code) current windows development recommendation. I've seriously lost all
track of how to just get up and going. I've tried UWP/WPF etc - they felt like
a bit of nightmare for quick and go, but the tooling now seems to have dropped
winforms? I couldn't get the form designer to actually show up even on a
WinForms project?

~~~
Ididntdothis
You can write Winforms like code in WPF and get better layout capabilities. If
you stay away from MVVM then WPF is pretty straightforward.

~~~
tigershark
Please don’t, if I happen to work on it I’ll burn it to the ground. I’ve
worked on plenty of WPF applications written like it was winforms and they all
sucks.

~~~
Ididntdothis
For quick one offs I still prefer WPF over Winforms even without MVVM and
thereby avoiding the learning curve. In the long run MVVM is probably better
(although I am not so sure on that either. I have seen plenty of nightmarish
“proper” WPF apps too)

------
daeken
Damn, this is fantastic. One big syntactical thing I should really put in a
proposal for is null-conditional returns. Turning

    
    
        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.

~~~
Koshkin
An interesting idea; it could be extended to other constructs - assignments,
method calls... Also, imagine having something like this:

    
    
      while (!return? foo) {
        foo = get_foo();
      }

~~~
oaiey
Oh please not. Hiding complexity is dangerous.

------
ThrowawayR2
> " _Top-level programs_ "

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?

~~~
jrimbault
In C# I'd like to able to :

\- 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.

~~~
Mindless2112
You can do

    
    
        using Console = System.Console;

~~~
jrimbault
The point is : the C# namespaces, default behaviors and general usage, are
only half of a good idea. Effectively importing every symbol in a namespace
into the local namespace by default is so obviously _bad_.

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.

------
dzonga
taking all the best features of F# and putting them on their golden child C#.
c# is looking elegant.

------
jeffdavis
What is an example of a really good codebase written in modern C#?

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.

~~~
_-david-_
My understanding is that the dotnet runtime and powershell are both decent
codebases.

[https://github.com/dotnet/runtime](https://github.com/dotnet/runtime)

[https://github.com/PowerShell/PowerShell](https://github.com/PowerShell/PowerShell)

~~~
jeffdavis
Looking at a random file in Powershell, the first thing I see is:

    
    
        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...](https://github.com/PowerShell/PowerShell/blob/15c2245af9748659643626db863540aed4d4f72e/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddMember.cs#L93)

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.

~~~
joshschreuder
Looking at object getter/setters in any OOP is likely to be pretty uninspiring
:)

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...](https://github.com/PowerShell/PowerShell/blob/15c2245af9748659643626db863540aed4d4f72e/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs)

~~~
jeffdavis
Yeah, clearly there's some code somewhere that does something. I just don't
understand why there are so many files and so much code that does nothing and
means nothing.

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.

------
mindfulplay
As usual a beautiful, beautiful language. As expected, they start with
something simple and build layers upon layers all connected via simple
concepts.

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)

------
thelazydogsback
As much as I love F#, C# now has enough of F#'s core features that I'll
probably use F# less due to the better tooling for C# code. (Resharper,
Ozcode, etc.) C# still needs DU's though... Meta-programming support is kinda
better if F#, but isn't great in either language unfortunately - you could
argue the as C# is based on Rosyln that it is actually better.

~~~
kqr
I'm viewing it exactly the other way around: if my co-workers have to learn
this stuff anyway, I can just as well just use F#, which implements these
things in more convenient ways.

------
pragmatic
This is great and all but I can't help but feel c# is finished and they are
adding more complexity for minimal convenience.

------
herogreen
I would like to know what is the future of Mono now that dotnet core is
crossplatform and Microsoft bought Xamarin.

Mono remains the best (only?) solution to call C# from C++ in a crossplatform
way using embedding.

~~~
oaiey
Well, Mono is now one of the two .NET runtimes shipped with .NET 5+. Like you
mentioned, it is better for embedded and porting. That the reason they I
integrate it.

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, ..).

~~~
kqr
How is that a good thing? Isn't it reminiscent of embrace, extend, extinguish?

~~~
oaiey
Mono was never usable for server workloads. Its niche was the same as it is
today: being portable and embeddable. .NET 5 gains that by integrating Mono.
The benefits for that use case is the better tooling and ecosystem of .NET 5.
With Xamarin, .NET Core and Unity doing one agenda every. NET dev wins. Mono
and the .NET Framework are dead.

.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.

------
archgoon
It seems using toplevel programs could make it harder to find the entry point
to a program. Is there an easy way, given a built assembly, to know which
source file the entry point is?

------
jinushaun
Every new version of C# seems to change what it means to write "colloquial
C#". I love it. These are all good changes.

------
polskibus
which visual studio version will support c# 9?

~~~
u7u7h
Now you can test C# 9 with Visual Studio Preview and .NET 5.0 preview
[https://visualstudio.microsoft.com/vs/preview/](https://visualstudio.microsoft.com/vs/preview/)
[https://dotnet.microsoft.com/download/dotnet/5.0](https://dotnet.microsoft.com/download/dotnet/5.0)

~~~
phillipcarter
Note: you can't use C# 9 with .NET 5 preview 4; you'll have to wait until .NET
5 preview 5 is released. You can use it with the latest VS preview, though.

~~~
polskibus
yes but when it comes out in full, will VS 2019 still support c# 9 or will I
have to buy new VS?

------
seemslegit
Positional records are a terrible idea, one of the best things about C# is
readability

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.

~~~
Jtsummers
I disagree. Automatic destructuring like this can be fantastic. Sure, if
you're just destructuring a variable there's not much gain. But this is much
smoother:

    
    
      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.

~~~
seemslegit
You are aproaching this from the mindset of the code author, but consider a
new contributor to a project reading for the first time, with positional
destructuring

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.

------
Koshkin
How does the .NET ecosystem fare these days compared to Java's? Whatever the
differences between the languages, on the surface of things it looks like _one
must be insane_ not to use Java:
[https://projects.apache.org/projects.html?language](https://projects.apache.org/projects.html?language)

~~~
shanemhansen
.NET ecosystem is large, but still windows-centric. If I was choosing between
java and C# for a startup, I'd definitely consider C# because it does seem to
be a better java (properties and LINQ are the first 2 things that come to
mind).

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.

~~~
The_rationalist
The point of C# being a better Java is nowadays mostly obscolete because of
Kotlin being THE better Java. As for LINQ see
[https://github.com/mythz/kotlin-linq-
examples/blob/master/RE...](https://github.com/mythz/kotlin-linq-
examples/blob/master/README.md)

~~~
foepys
Why don't people understand that LINQ isn't just a C#-ish way to write SQL-
like statements? So many people are comparing their libraries to LINQ without
understanding what it actually does.

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.

~~~
scarface74
And the Mongo Linq library is often. For $reasons I worked on an
implementation that had to support Sql Server and Mongo. The models and the
Linq expressions worked across both and were translated appropriately. We just
passed around a bunch of

    
    
      Expression<Func<T>>

