Hacker News new | past | comments | ask | show | jobs | submit login
A Preview of C# 8 [video] (msdn.com)
125 points by plurby on Aug 25, 2017 | hide | past | favorite | 98 comments




Glad to see this Dart feature appearing in C#:

  Asynchronous Streams
Now you can "yield" Task<T> (~ Future<T> in Dart) and construct LINQ chains in an asynchronous fashion. I hope it streamlines reactive programming greatly.

[1] Dart - Asynchronous Programming: Streams https://www.dartlang.org/tutorials/language/streams

[2] .NET Futures: Asynchronous Streams https://www.infoq.com/news/2017/05/async-streams


Very excited about the Nullable Reference Types.

Besides that, the feature I want most in C# is enum exhaustion checking. So I can write:

  enum Color { red, green, blue };
  public static string SuperheroFromColor(Color c)
  {
    if (c == Color.red)
    {
      return "Superman";
    }
    else if (c == Color.green)
    {
      return "Green Lantern";
    }
    else if (c == Color.blue)
    {
      return "Spiderman";
    }
  }
and not get a compiler error (that not all code paths return a value). But if I added "yellow" as an enum option, then I would get a compiler error. I realize that Color can be cast from an out-of-range int, so it's a little complicated. I'm willing to put something extra after the last else:

  unreachable return null;
or use a special switch statement. I just want something so the compiler checks that I have accounted for all normal enum values.

Is anyone talking about such a feature, or where would I request it? Can I write it myself as a Roslyn extension?


I wrote myself a compiler extension to check this for me:

https://github.com/abjennings/EnumAnalyzer


I know this doesn't solve your problem in C#, but F# gives you a compiler warning in such a case. The following code compiles without warnings or errors:

  type Color = Red | Green | Blue
  
  let superheroFromColor c =
      match c with
      | Red -> "Superman"
      | Green -> "Green Lantern"
      | Blue -> "Spiderman"
However, if you add Yellow as a new case to the Color discriminated union without adding a corresponding match pattern everywhere you match a Color value, you get a compiler warning:

  type Color = Red | Green | Blue | Yellow
  
  ...
  
      match c with
  ----------^
  warning FS0025: Incomplete pattern matches on this expression. For example, the value 'Yellow' may indicate a case not covered by the pattern(s).
Aside: notice how terse and readable the code is compared to the C# equivalent; F# tends to have a high signal-to-noise ratio.


Use the switch statement without a default clause. If you haven't exhausted the options, you get an error.


A compile-time error?

It doesn't do that for me on VS2012 or in .NET Fiddle: https://dotnetfiddle.net/f4NSvf


clicking that link, i see a 'not all code paths return' error.


I can see how that's unclear.

That fiddle was supposed to be an example where I did exhaust all the options, so I shouldn't get a compiler error. In any case, to make the error go away, I add a "return null" or throw an exception at the end: https://dotnetfiddle.net/I7LXkW

Then I want to be able to add a "yellow" option to the enum and get a compiler error, but there is no error: https://dotnetfiddle.net/IIUfye

That's the bigger problem. I should've shared that one.

Can someone show me a fiddle of a C# program that compiles, but gives a compiler error when I add another value to the enum?


There isn't one. You're correct, this is not something that C# can do.

To be even more specific, it's not doable in C#, because enum types actually have the complete set of values of the underlying integer type. Thus, this is valid:

   Color c = (int)123;
So enum doesn't actually limit the value domain of the integer type. It just gives names to some of the values, while still allowing all other values. If you actually mean to constrain the values as part of pre-contracts in your public API, you have to check for that yourself, e.g. via `Enum.IsDefined`.

So, getting back to your scenario - "Yellow" was always an option. It's just that you gave it a name when it didn't have one before. Consequently, for switch to be truly exhaustive, it'd have to check for all 2 billion possibilities.

This all is the unfortunate consequence of inheriting enum design from C++, and retaining its very low-level semantics. But now that it's there, and has been there since C# 1.0, they're stuck with it. I suspect any future advances in this area will come with a new construct that would be a "better enum" - e.g. case classes or full-fledged ADT variants. Now that the language has pattern matching, it's begging for something like this.


I wrote a compiler extension to help me:

https://github.com/abjennings/EnumAnalyzer

It doesn't analyze the control flow or anything like that. It just looks for places where I throw a certain exception, then checks the surrounding code block to make sure all the defined enum values are mentioned at least once.

It definitely doesn't handle all the corner cases. But I think it's 90% of the benefit for 10% of the cost. Also, I learned to write compiler extensions...


There is a proposal for "sealed enums" on the C# language repo that have the semantics you are looking for.

https://github.com/dotnet/csharplang/issues/782


Kotlin has been doing null safety since release. I suggest checking it out if that sort of thing excites you. It's probably my favorite language currently.


You're asking for a language change to fix poorly written code. The final else if() is redundant, if you change it to a simple else you remove the "not all code paths return a value" issue and remove a redundant check. This requires you to consider the "and others" possibility, rather than the compiler making assumptions about the type's definition.

Plus what you're asking for is a maintenance nightmare; since changing the type (Color) in one part of the code can break method definitions in another part of the code (inc. other assemblies).

I'd hope they would never support what you're asking for.


He's asking for exhaustiveness checking of pattern matching algebraic data types. Many languages have had this for essentially forever.

It does sometimes mean that when you update some code, you have to update a bunch of other things. But it's rarely spurious. Usually those other things are broken by failing to consider the new possibility.

In the long term, it's a maintenance win.


But C# enums are a terribly weak data type, not a good implementation for the semantic you're looking for at all.

Better to ask for a C# union type and matching syntax.


If I add a "yellow" option to the enum, then I _want_ to get compiler errors (or warnings) about all the places in my code that need to handle that new case. That's what compilers are for, that kind of busy work.

Is there a way to write that SuperheroFromColor function so that I will get a compiler error (or warning) if another option is added to the enum? (Imagine that function is far away from the Color definition so it's not visually obvious.)

When I create an enum with three possible values, I reason about it as having only three possible values. As long as I never cast from an int, that should be true, right? So I don't want to consider the "and others" possibility. It's hard to even think about what to do in that situation, since it shouldn't happen.

I said that I'm willing to put some keyword before or after the if statement to tell the compiler to make sure I'm handling all valid enum values. So it can only give me these errors (or warnings) when I ask for them.

I think pattern matching in Haskell will make sure you handle all possible cases and give you a compiler error if you don't. I'm asking for a "poor-man's version of pattern matching for enums" in C#.


By turning the "else if" into an "if" you introduce a silent bug when Color.yellow is added, since the final else clause would now have to deal with both blue and yellow correctly.

Adding a new member to the Color enum should break code that isn't written to handle it: which is any code written before Color.yellow was introduced.


Created a compiler extension to help me:

https://github.com/abjennings/EnumAnalyzer


This looks great. I just stepped back into java for a one off project, after not touching it for about 15 years. I was surprised how antiquated it felt compared to modern C#. Glad to see Microsoft is not letting the language languish.


Oracle basically destroyed every cool technology they inherited.


I know everybody hates Oracle here, but Java 7, 8 and the upcoming 9 releases, all of them under Oracle's control, have had more improvements than Sun did in the years prior to the acquisition. How's that destroying anything?


* Ugly Oracle DB style contracts

* Scaring potential customers away with said contracts and suing customers

* Google walking out on Java going with Kotlin instead....boom billions of users moving to a different language. Still on the JVM though....but that's not a hard requirement.


In spite of the lawsuits, Google is actually a big contributor to the OpenJDK and a common presence at Java Languages Summit.

As for Kotlin, it remains to be seen how much uptake it will actually take.

Despite all attempts from Apple to push Swift, many keep on using Objective-C.


> As for Kotlin, it remains to be seen how much uptake it will actually take.

Kotlin is a language made by JetBrains which happens to be the creator of the official Android IDE. So yes the push will be strong from both Google and JetBrains. Java was a bit more modern than Objective-C but if I see what our junior Android dev has to type and type and type and type in Java to do the same as I do in Swift....kids get bored quick you know...

> Despite all attempts from Apple to push Swift, many keep on using Objective-C.

I don't encounter many during my job as an iOS developer. I encounter people maintaining an existing Objective-C codebase that isn't worth switching and adding 10MB of application weight for Swift.

I guess for all green fields projects 80% is Swift. There's just no reason to use Objective-C anymore since Swift 3 so the only people that choose it are:

a) People interfacing with C / C++ a lot b) People creating a framework that needs to play nice with both c) People stuck in old ways


It doesn't matter if kids get bored, rather what the people giving the money want to get.

So far, I haven't found an enterprise customer that was willing to allow anything but Java, unless it is required by the tooling.

For example Scala only when making use of Spark.

I am happy that Kotlin is now an approved language on Android, but trying to kill Java on JVM, C on UNIX, JavaScript on the browser, ....

It is never going to go away, and those that embrace the language of the platform are in advantage.


It is absolutely not destroyed but I'm more hesitant about choosing it than I used to be.


The only time Java was cool was in 1995. But almost right off the bat, the language was ruined by an incredible desire to not even potentially break or change anything -- this is what got us inner classes for event handling -- and every design decision since.

If anything, Java (the language) is probably improving at a faster rate now than ever before but much of the damage is already done.


The only time Java was cool was in 1995.

Has been cool the last few years as well.



So far they have improved Java much more than Sun ever cared to do on its last years.


If someone doesn't know Java and c#, which one would u recommend learning ? Which one is more enjoyable and has better ecosystem? Given both are strong in European markets.


I work with both.

Extending a bit iainmerrick's answer, it depends on what you want to do.

C# is stronger on the desktop when focusing on Windows or game development.

Thanks to .NET Native, the UWP teams now are doing most of their demos on C#, even when many of the performance critical COM componentes are actually written in C++.

For web related development, usually only companies with focus on Microsoft software tend to pick ASP.NET solutions.

Now .NET Core might change that, but until 2.0 it was mostly a thing for early adopters. Currently enteprise class databases like Oracle are yet to support .NET Core drivers.

For mobile development C# is also a good option, thanks to Xamarin.

Another area where .NET is strong is on life sciences, integrating .NET with COM/OCX drivers for medical devices or laboratory robots.

Java's support is stronger on the web, distributed computing, big data, embedded devices and of course Android.

Swing and JavaFX can be quite usable, but require a bit of graphics programming skills, so they got the fame of not being easy to produce nice results.

For web applications there are lots of stacks JEE, Spring, Netty, Tomcat, JBoss, Jersey,....

Also all mainframes also support Java, companies like Gemalto, Ricoh and Cisco have Java OSes on their devices.

IBM, PTG, Aicas, MicroEJ, Skelmir are a few exemples of companies selling commercial JDKs for embedded development.

Regarding language features C# and F# are more enjoyable, but the open source culture is stronger on the Java side, and there are also alternative languages on the JVM.

However on the Java projects I usually work, the customers are very conservative and tend to only accept straight Java code.

Also both stacks tend to copy ideas from one another, so it is possible to kind of keep on track with both.

The hard part are those areas that are different like lack of values in Java or the way equality works.

I love Visual Studio, my favourite Java IDEs are Netbeans and Eclipse. InteliJ and Android Studio need to be tuned to run on my hardware.


>Swing and JavaFX can be quite usable, but require a bit of graphics programming skills

By this, do you mean skills with computer graphics programming versus GUI programming? As in things like double-buffering, BitBLT, etc.

https://en.wikipedia.org/wiki/Bit_blit

And if so, why are those needed for Swing and JavaFX?


A bit, yes.

Like in any GUI toolkit, one needs to have the taste and knowledge how to make into reality the wishes of a designer, or be a designer themselves.

On Swing's case taking the effort of reading books like "Filthy Rich Clients" and "Swing Hacks: Tips and Tools for Killer GUIs".

http://filthyrichclients.org/

https://joshondesign.com/c/writings

And be aware of cool 3rd party components like http://www.jgoodies.com/

The biggest problem with Swing is that Sun wasn't that good understanding the desktop, so although Swing is quite capable it has lousy defaults, like requiring the native look and feel to be explicitly configured, or making it too easy to run everything on the main thread.

On JavaFX's case, it is easier to use, but similar to using QML, XAML or the Web.

Following blogs like FX Experience http://fxexperience.com/ helps discovering cool components.

For those that care about UI/UX, GUI programming is graphics programming.

There is only so much that the default controls can do in any toolkit, extending them, customizing how they behave, or even creating them from scratch requires knowledge of graphics programming, because in the end you are putting pixels into the screen.


Thanks for the detailed answer; very interesting info. I had done a bit of Win32 GUI programming much earlier (I mean in C, had also done some VB and Delphi work), and had read some books about it. I remember reading about owner-drawn controls, etc. Good stuff.


Having used a bit of both, I'd say C# is a slightly better and more enjoyable language.

They're really very similar, so if you learn one, many of the skills will transfer easily over to the other -- should only take a few weeks of serious use to figure out all the subtle differences.

Java has the better ecosystem. C#'s standard infrastructure and tooling is a bit of a mess, although if you're just targeting Windows (or Unity) maybe it's OK. C# is even less "write once run anywhere" than Java, because there are all sorts of different profiles with different subsets of the standard library available.


Come on, default method in interface is a Java 8 feature, what's the coolness of C#is there?


Non-nullability is you know quite a thing. Even in it's current half-baked form. That default method interface is not something that I would touch on a day-by-day basis.


Java is not designed by a single company, in spite of Oracle's stewardship.

And it runs in many systems that .NET still doesn't, so adding features without doing a Python 3 is very important.


I'll crank up those `null` assignments to non-optional references warnings up to compiler errors. There's really no reason to ship software that doesn't explicitly declare something as nullable.

The `!`'s are always code smells. I hope I can turn them into warnings or build errors.


I wouldn't say they're always code smells. Like they say in the video, a call to the 'myString.IsNullOrEmpty()' extension method is a null check, but there's no way to prove that to the compiler.


I think that's more of a compiler problem then. Also what's missing is the unwrap syntax to easily transform between nullable and non-null references. What you really want is to operate on a non-null version of that reference if it's proven to be non-null, this is really the Achilles heel of this particular implementation. You're still checking for null all over the place, it's just better checked.

    // Unholy mix of Swift and C# syntax ahead!
    if var unwrappedString = wrappedString && unwrappedString != "" {
         unwrappedString.Length();
    }
Where the `if var unwrappedString = wrappedString` part would unwrap the var and return a `bool` at the same time which is `true` if it wasn't `nil`.

Swift's nil-checking / unwrapping syntax is really short and with some clever usage of `map` or `flatMap` you can still have one-liners albeit a bit more verbose - but much more secure.

Example of using map:

    let myTitle = myObject?.title.map { "Item \($0)" } ?? "No title"
This code can't even theoretically crash anymore and doesn't force unwrapping with `!` as a traditional approach would do:

    let myTitle = myObject?.title != nil ? "Item \(myObject!.title!)" : "No title"


You can totally do this in C#, since it has lambdas, and you can use the extension method to add "map" to nullable references of arbitrary types. It also has ??.

The problem is that lambdas aren't free. For something as simple as a null check, the overhead of a lambda is excessive. Zero-cost lambdas are possible, but require a new type of lambda that cannot escape the enclosing scope, all reflected in the type system.


The reason is that you have millions of lines of existing code written with "nullable by default" assumption in effect, and you need to be able to gradually migrate that.


I think ReSharper already warns about a lot of those so if you've followed up on those warnings already you're in a good shape to switch to compiler errors. I don't think it'll take a long time to fix all new warnings even on larger projects. But the gains are huge.


Great to see these Swift features[1] appearing in C#:

* Nullable Reference Types This makes it so much easier to reason about references. I always found it strange that C# had nullability on value types, but not on reference types.

* Default Interface Implementations Inherit an interface, and get an implementation "for free". This makes for a very powerful way to define interfaces and default implementations.

* Extension Everything As noted in the video/text, the current syntax feels a bit weird -- having to use a static class.

[1]: Not saying these are exclusive to Swift, or Swift was the first to implement them.


In the video, Torgersen says the nullability feature was inspired by TypeScript. Torgersen says he consulted TypeScript creator Anders Heijlsberg to build the nullable reference feature.

As a heavy TypeScript user myself, it was easy to see the parallels between the designs: question mark nullability, the compiler-enforced nullability checks rather than runtime-enforced, "dammit operator" to override the compiler. All shared between TypeScript and C#.

I love this feature in TypeScript; it's help me find numerous bugs and helps me reason about my code. I'm looking forward to using it in C#.


Just wanted to point out that besides creating Typescript, Anders has been the Lead Architect on C# since 2000.


For the past couple of years I have been the lead designer of C#. Anders and I took a break to help create TypeScript, and then he stayed on as it's lead designer, while I returned to take over C#.

Anders and I meet every week to compare notes, and I make sure to get his input on major new features in C#.


Apparently he is mostly focused on Typescript nowadays, and not so much on C#, although he still participates on its development.

At least given his latest interviews on Channel 9 and BUILD sessions.


He was also the original author of Turbo Pascal and the chief architect of Delphi.

https://en.wikipedia.org/wiki/Anders_Hejlsberg


> I always found it strange that C# had nullability on value types, but not on reference types

Version 1.0 of C# was the same as Java: Nullable reference types and non-nullable value types. Nullable value types didn't come until version 2.0 but at that point ir was too late to make reference typed non-nullable.

I'm glad they're actually putting the effort to fix this issue now. It's a huge task given the amount of legacy code out there.


I am so, so excited for Default Interface Implementations. Abstract classes are great but when you want (have) to go down a different inheritance tree this will be so nice.


With the introduction of this feature, is that the only difference between the two?


Abstract classes can have state, default interfaces can only have behavior. So state is still single-inheritance, while behavior is effectively multiple-inheritance now.


Swift extensions do not have the ability to add variables to the scope of the class they extend or into their own private scope. Perhaps because the compiler times would crash through the roof but I find it very limiting. I do use extensions in Swift but I prefer to factor out any code into it's own class once it needs to touch any kind of state.


In Obj-C extensions you can add variables with the help of Obj-C runtime.


Nullable reference without "if let" keyword is disaster


"If let" could be easily mirrored by a pattern in C#, and we are starting to discuss that.

However, that's a new way to check for null in the language, where what we need is to recognize the ways people are already checking for null in billions of lines of code. Therefore, the priority is to do a good flow analysis that will just understand when a nullable variable can be assumed to not be null (e.g. after a check, a non-null assignment, etc.), and then let you dereference without challenge.


If c# 8 has good flow for checking null, then no need "if let". If let also has disadvantage, backward compartibility. For example, maybe i want change my logic class to c# 2


"If let" leads to code that is hard to read IMO. I'd rather be able to easily tell the difference between conditional statements and assignments.

Another Swift feature that I think leads to very poor readability is trailing closures.


Without if let, you must add one line for declare local variable. And also must add exclamation mark


C# 7.0 already has the 'is' pattern matching operator that returns true/false and can introduce a new variable that is not null.


> Default Interface Implementations

So basically multiple inheritance?


For method lookup, but not for object structure. That's really important from an implementation viewpoint because field accesses can just be done as a simple offset without any complexity round the type.


It's multiple inheritance of behavior, but not of state.


Except for state...


Interesting, the new type IAsyncEnumerable is like an Observable. But it's pull instead of push. Ie it supports backpressure like the Reactive Streams [1] standard in the JVM world. I seem to recall that Erik Meijer had some strong opinions when that standard was forming on backpressure and anything that's not purely push based.

Personally as a developer I really like having the choice whether to buffer in one place in my system (using a persistent queue f.i.) and have the rest of the system cooperate in tandem without running out of memory f.i. Or to choose to ignore elements when stuff is just going to fast. Etc. I feel more in control of the behaviour under load of my system.

I guess Lightbend was onto something when they took the old EAI notion of backpressure (as f.i. described in Gregor Hohpes book) and implemented it in stream processing and started an interoperability standard around it.

[1] http://www.reactive-streams.org/


I feel like I've been waiting for non-nullable reference types for forever.

What they talk about here, with explicit nullable reference types is so close but stumbles at the last hurdle. Having some kind of opt in on the compiler that makes regular references non-nullable is great for new projects (and arguably the best thing for the language itself), but leaves all legacy code out in the dark. You can't switch on a compiler option like this on any big existing project without massive effort. (And massive effort means management approval and planning and justification)

They got the case by case opt on the wrong part of the feature. It's really the non-nullability of a reference that's most important to be able to be opted in to on a case by case basis. (And case by case opt in means low effort, so it doesn't need big up front approval or planning, you just get on and write better code with fewer bugs.)

What's really needed is something like this

    String! s = null;
Where the ! makes the s reference non-nullable, so any attempt to assign null (or anything that could be null) to it is a compiler error.

And it's so disappointing because he comes so so close to that at the end with his talk of s!. as a way to say that you know something is not null, but it just doesnt quite get the benefit right.

It's non-nullability of reference types that should be the central feature here.

I'm just really hoping that these guys know what they are doing, and it's just he couldn't explain the subtleties in a short video, and this is going to turn out working the right way in the end.


At first we did think of this as a way to add non-nullable reference types to C#, maybe with a `string!` syntax as you propose.

The feature only really started to gel when we realized the important feature was nullable reference types. The thing is, in most code, most things aren't actually supposed to be null. So we want non-null to be the default.

When you start marking the things that should be null as such, you'll be protected from dereferencing those without a check. That's what actually prevents you from getting null-reference exceptions!

And once you've marked them all (usually a fraction of your type annotations), null really doesn't have a place in the remaining spots, and you can turn on the non-null check to eradicate those.

This leaves you with the smallest number of places to update your existing code, and leaves new code the cleanest.


You make a good point, although personally my codebase is split into enough projects that I think the transition will be manageable.

If it's just a compiler warning (and you don't treat warnings as errors) then can't you leave it on and do the work gradually? Or turn it on for a day, do some work, and turn it off again? You have to eat the elephant somehow.

Also, even if you make the non-nullability opt-in on a case-by-case basis, don't you still need a compiler switch to turn on occasionally and see what remains to be done?


The problem with that approach is that if you have it there, people will forget to use it, and still end up with tons of nullable references that really should be non-nullable. In order to be effective at catching bugs, non-nullability has to be opt-out rather than opt-in.

Yes, this sucks for existing code. I suspect that we'll get some kind of file-level switch, so that you can port things one class at a time - there's no reason why that switch has to have the same value for all files in the project.


No reason why there can't be both. Syntax to opt in one at a time for old projects, and a compiler option for new projects.

Yeah, or a file level switch would do, that would be fine. As long as there is some way of transitioning a project little bit at a time.

I hope we get one of those options


Why is default interface implementation controversial? I get it for moving existing .Net functionality around but for development of new code, what's the downside.

Coming from C++ it seemed like C# interfaces (and Java at the time) felt like a punishment. Now I'm sort of used to them.


It requires runtime (VM) support. That's always a much higher bar to clear than pure language features.


C# 7 was release a few months ago. The video is just a prototype of what C# 8 could have.


The current version is 7.1 already.


There's some interesting and controversial stuff in here. I am very excited about extension everything. I also like the new extension method syntax; much cleaner and a much clearer expression of intent.


I'm curious what parts you feel are controversial? I don't disagree. I haven't looked it over yet. But sometimes I worry that C# is adding too many features to keep up with what's hot at the moment.

Lambdas vs nested functions is an example that comes to mind (during the Microsoft Build conference presentation of the feature, the presenters jokingly admitted that nested functions arose from Javascript's popularity).

I felt like the value-add of nested functions over lambdas, versus the growth of language complexity, was not great enough to add nested functions as a language feature. (Of course, that's just my opinion.)

But the bigger question is, what's the threshold where software and languages go from being "feature rich" to "bloated"? And are there cases in the past where the corporate stewards of a language have found that sweet spot?

C# has been a great language. I use it every day.

But it feels like the inevitable end game for this language, and maybe every language with corporate stewardship, is that the pressure to release new versions to "keep up with what's hot" eventually ends in the death of the technology by a thousands cuts (where, in this case, by cuts we mean unnecessary features).

(To be fair, the language stewards so far have been batting 900. They've generally done a great job at this so far.)


By 'nested functions' do you mean local functions? Another reason for them is that they can sometimes bring performance improvements over lambdas.


Feels like extensions tend to make it hard to find out what you need to import to make things work as intended. Maybe visual studio proper is better at inference for it? Will only autocomplete methods that are actually in scope as far as I can tell.


It will only auto-complete methods that are in scope (the alternative would be a bit crazy) however Visual Studio is smart: if you type in a method you know exists you can press CTRL-. to get it to add the correct using statement to bring that extension method into scope.


You can turn on an Intelisense option to show methods that would be in scope, if you had the using statement, and it will auto add the using statement if you select that. Really helpful.


Is this a Resharper thing?


Yes, it looks like that's "Import Symbol Completion" - https://www.jetbrains.com/resharper/features/code_completion...


No, but after looking at VS 2017 on my pc and VS for Mac, apparently it's only a feature in VS for Mac- at least from what I could find. I imagine that gets changed soon but yea.

If you use VS for Mac its under Preferences > Text Editor > Intellisense > Show Import Items


In VS 2017, if you use a method that's an extension method, and don't have the namespace imported, it'll show the auto-correction bulb with an offer to import it.

Better yet, if it's from a NuGet package, it'll offer to install one (or several, if there are multiple candidates).


Compared to say Python, it does act a bit like importing free functions without explicitly naming them, but you do get the bonus of type-based dispatch and overloading.

    using System.Linq;
    foo.Select(x => bar);

    from itertools import *
    imap(foo, lambda x: bar)


Correct, it can be maddening at times when you want to use LINQ methods but forgot to include System.Linq.


What helps me cope is that in Visual Studio you can type the extension method's name and ctrl-. to get an "import namespace" quick fix suggestion. It even works when you type it with wrong casing (which happens to me a lot because I'm a really lazy typist). I'm really glad the VS team has been putting more of those in.


Would "extension interfaces" be equivalent to "type classes" in Haskell and/or "traits" in Scala or Rust?


There's a great proposal for adding type classes to C# here: https://github.com/MattWindsor91/roslyn/blob/master/concepts...

And I discuss some ways that could be integrated with the extension everything proposal here: https://github.com/dotnet/csharplang/issues/164

The problem with both is that there's a new notion of "shape" or "concept" that's different from interfaces. It would be nice to just use interfaces for this (which is what I hint at in the video), but that comes with its own downsides and limitations.


Being able to take an instance Person and make it be an Employee without changes to the Person class definitely sounds like ad hoc polymorphism. In Scala the equivalent of Haskells type classes is implicits though. Not traits. I do wonder if this 'extension interface implementation' feature would support the same inferencing that type classes in Haskell and implicits in Scala do. So that might be a difference.


> In Scala the equivalent of Haskells type classes is implicits though. Not traits.

Really? I'm not an expert but everything I've read until this implies the opposite. Besides, C# already has implicit conversions, and they're different from type classes in that they convert, not extend. Once an int is implicitly converted to a double, it's always a double from within the function that converted it, not just "representing" a double. So strictly less powerful than polymorphism. My understanding that type classes were the way out of that, and traits were Scala's equivalent. Is that not correct?


It's implicit arguments, not implicit conversions that enable type classes in Scala, although the class is usually represented by a trait e.g.

    trait Show[T] { def show(v : T): String }
    implicit object ShowInt extends Show[Int] {
	def show(i: Int) = i.toString
    }
    def showLine[T](v : T)(implicit show: Show[T]): Unit = {
        println(show.show(v))
    }


Nice, that makes it more clear. Thanks!


Type classes in Scala typically entail a mix of features: implicits, traits, and higher kinded types.

Assume you're thinking about C#'s extension methods, which in Scala are achieved via implicit classes.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: