What’s New in C# 7.0

Update (4/2017): See New Features in C# 7.0, the update to this post.

What follows is a description of all the planned language features in C# 7.0. With the release of Visual Studio “15” Preview 4, most of these features are coming alive. Now is a great time to take them for a spin and tell us your thoughts!

C# 7.0 adds a number of new features and brings a focus on data consumption, code simplification and performance. Perhaps the biggest features are tuples, which make it easy to have multiple results, and pattern matching which simplifies code that is conditional on the shape of data. But there are many other features big and small. We hope that they all combine to make your code more efficient and clear, and you more happy and productive.Please use the “send feedback” button at the top of the Visual Studio window to tell us if something is not working as you expect, or if you have thoughts on improvement of the features.There are still a number of things not fully working in Preview 4. In the following I have described the features as they are intended to work when we release the final version, and called out in notes whenever things don’t yet work as planned. I should also call out that plans change – not least as the result of the feedback we get from you! Some of these features may change or disappear by the time the final release comes out.If you are curious about the design process that led to this feature set, you can find a lot of design notes and other discussion at the Roslyn GitHub site.

Have fun with C# 7.0, and happy hacking!

Out variables

Currently in C#, using out parameters isn’t as fluid as we’d like. Before you can call a method with out parameters you first have to declare variables to pass to it. Since you typically aren’t initializing these variables (they are going to be overwritten by the method after all), you also cannot use var to declare them, but need to specify the full type:

public void PrintCoordinates(Point p)
    int x, y; // have to "predeclare"
    p.GetCoordinates(out x, out y);
    WriteLine($"({x}, {y})");

In C# 7.0 we are adding out variables; the ability to declare a variable right at the point where it is passed as an out argument:

public void PrintCoordinates(Point p)
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");

Note that the variables are in scope in the enclosing block, so the subsequent line can use them. Most kinds of statements do not establish their own scope, so out variables declared in them are usually introduced into the enclosing scope.

Note: In Preview 4, the scope rules are more restrictive: Out variables are scoped to the statement they are declared in. Thus, the above example will not work until a later release.

Since the out variables are declared directly as arguments to out parameters, the compiler can usually tell what their type should be (unless there are conflicting overloads), so it is fine to use var instead of a type to declare them:

p.GetCoordinates(out var x, out var y);

A common use of out parameters is the Try... pattern, where a boolean return value indicates success, and out parameters carry the results obtained:

public void PrintStars(string s)
    if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); }
    else { WriteLine("Cloudy - no stars tonight!"); }

Note: Here i is only used within the if-statement that defines it, so Preview 4 handles this fine.

We plan to allow “wildcards” as out parameters as well, in the form of a *, to let you ignore out parameters you don’t care about:

p.GetCoordinates(out int x, out *); // I only care about x

Note: It is still uncertain whether wildcards make it into C# 7.0.

Pattern matching

C# 7.0 introduces the notion of patterns, which, abstractly speaking, are syntactic elements that can test that a value has a certain “shape”, and extract information from the value when it does.

Examples of patterns in C# 7.0 are:

  • Constant patterns of the form c (where c is a constant expression in C#), which test that the input is equal to c
  • Type patterns of the form T x (where T is a type and x is an identifier), which test that the input has type T, and if so, extracts the value of the input into a fresh variable x of type T
  • Var patterns of the form var x (where x is an identifier), which always match, and simply put the value of the input into a fresh variable x with the same type as the input.

This is just the beginning – patterns are a new kind of language element in C#, and we expect to add more of them to C# in the future.

In C# 7.0 we are enhancing two existing language constructs with patterns:

  • is expressions can now have a pattern on the right hand side, instead of just a type
  • case clauses in switch statements can now match on patterns, not just constant values

In future versions of C# we are likely to add more places where patterns can be used.

Is-expressions with patterns

Here is an example of using is expressions with constant patterns and type patterns:

public void PrintStars(object o)
    if (o is null) return;     // constant pattern "null"
    if (!(o is int i)) return; // type pattern "int i"
    WriteLine(new string('*', i));

As you can see, the pattern variables – the variables introduced by a pattern – are similar to the out variables described earlier, in that they can be declared in the middle of an expression, and can be used within the nearest surrounding scope. Also like out variables, pattern variables are mutable.

Note: And just like out variables, stricter scope rules apply in Preview 4.

Patterns and Try-methods often go well together:

if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }

Switch statements with patterns

We’re generalizing the switch statement so that:

  • You can switch on any type (not just primitive types)
  • Patterns can be used in case clauses
  • Case clauses can have additional conditions on them

Here’s a simple example:

    case Circle c:
        WriteLine($"circle with radius {c.Radius}");
    case Rectangle s when (s.Length == s.Height):
        WriteLine($"{s.Length} x {s.Height} square");
    case Rectangle r:
        WriteLine($"{r.Length} x {r.Height} rectangle");
        WriteLine("<unknown shape>");
    case null:
        throw new ArgumentNullException(nameof(shape));

There are several things to note about this newly extended switch statement:

  • The order of case clauses now matters: Just like catch clauses, the case clauses are no longer necessarily disjoint, and the first one that matches gets picked. It’s therefore important that the square case comes before the rectangle case above. Also, just like with catch clauses, the compiler will help you by flagging obvious cases that can never be reached. Before this you couldn’t ever tell the order of evaluation, so this is not a breaking change of behavior.
  • The default clause is always evaluated last: Even though the null case above comes last, it will be checked before the default clause is picked. This is for compatibility with existing switch semantics. However, good practice would usually have you put the default clause at the end.
  • The null clause at the end is not unreachable: This is because type patterns follow the example of the current is expression and do not match null. This ensures that null values aren’t accidentally snapped up by whichever type pattern happens to come first; you have to be more explicit about how to handle them (or leave them for the default clause).

Pattern variables introduced by a case ...: label are in scope only in the corresponding switch section.


It is common to want to return more than one value from a method. The options available today are less than optimal:

  • Out parameters: Use is clunky (even with the improvements described above), and they don’t work with async methods.
  • System.Tuple<...> return types: Verbose to use and require an allocation of a tuple object.
  • Custom-built transport type for every method: A lot of code overhead for a type whose purpose is just to temporarily group a few values.
  • Anonymous types returned through a dynamic return type: High performance overhead and no static type checking.

To do better at this, C# 7.0 adds tuple types and tuple literals:

(string, string, string) LookupName(long id) // tuple return type
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal

The method now effectively returns three strings, wrapped up as elements in a tuple value.

The caller of the method will now receive a tuple, and can access the elements individually:

var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");

Item1 etc. are the default names for tuple elements, and can always be used. But they aren’t very descriptive, so you can optionally add better ones:

(string first, string middle, string last) LookupName(long id) // tuple elements have names

Now the recipient of that tuple have more descriptive names to work with:

var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");

You can also specify element names directly in tuple literals:

    return (first: first, middle: middle, last: last); // named tuple elements in a literal

Generally you can assign tuple types to each other regardless of the names: as long as the individual elements are assignable, tuple types convert freely to other tuple types. There are some restrictions, especially for tuple literals, that warn or error in case of common mistakes, such as accidentally swapping the names of elements.

Note: These restrictions are not yet implemented in Preview 4.

Tuples are value types, and their elements are simply public, mutable fields. They have value equality, meaning that two tuples are equal (and have the same hash code) if all their elements are pairwise equal (and have the same hash code).

This makes tuples useful for many other situations beyond multiple return values. For instance, if you need a dictionary with multiple keys, use a tuple as your key and everything works out right. If you need a list with multiple values at each position, use a tuple, and searching the list etc. will work correctly.

Note: Tuples rely on a set of underlying types, that aren’t included in Preview 4. To make the feature work, you can easily get them via NuGet:

  • Right-click the project in the Solution Explorer and select “Manage NuGet Packages…”
  • Select the “Browse” tab, check “Include prerelease” and select “nuget.org” as the “Package source”
  • Search for “System.ValueTuple” and install it.


Another way to consume tuples is to deconstruct them. A deconstructing declaration is a syntax for splitting a tuple (or other value) into its parts and assigning those parts individually to fresh variables:

(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
WriteLine($"found {first} {last}.");

In a deconstructing declaration you can use var for the individual variables declared:

(var first, var middle, var last) = LookupName(id1); // var inside

Or even put a single var outside of the parentheses as an abbreviation:

var (first, middle, last) = LookupName(id1); // var outside

You can also deconstruct into existing variables with a deconstructing assignment:

(first, middle, last) = LookupName(id2); // deconstructing assignment

Deconstruction is not just for tuples. Any type can be deconstructed, as long as it has an (instance or extension) deconstructor method of the form:

public void Deconstruct(out T1 x1, ..., out Tn xn) { ... }

The out parameters constitute the values that result from the deconstruction.

(Why does it use out parameters instead of returning a tuple? That is so that you can have multiple overloads for different numbers of values).

class Point
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public void Deconstruct(out int x, out int y) { x = X; y = Y; }

(var myX, var myY) = GetPoint(); // calls Deconstruct(out myX, out myY);

It will be a common pattern to have constructors and deconstructors be “symmetric” in this way.

As for out variables, we plan to allow “wildcards” in deconstruction, for things that you don’t care about:

(var myX, *) = GetPoint(); // I only care about myX

Note: It is still uncertain whether wildcards make it into C# 7.0.

Local functions

Sometimes a helper function only makes sense inside of a single method that uses it. You can now declare such functions inside other function bodies as a local function:

public int Fibonacci(int x)
    if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));
    return Fib(x).current;

    (int current, int previous) Fib(int i)
        if (i == 0) return (1, 0);
        var (p, pp) = Fib(i - 1);
        return (p + pp, p);

Parameters and local variables from the enclosing scope are available inside of a local function, just as they are in lambda expressions.

As an example, methods implemented as iterators commonly need a non-iterator wrapper method for eagerly checking the arguments at the time of the call. (The iterator itself doesn’t start running until MoveNext is called). Local functions are perfect for this scenario:

public IEnumerable<T> Filter<T>(IEnumerable<T> source, Func<T, bool> filter)
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (filter == null) throw new ArgumentNullException(nameof(filter));

    return Iterator();

    IEnumerable<T> Iterator()
        foreach (var element in source) 
            if (filter(element)) { yield return element; }

If Iterator had been a private method next to Filter, it would have been available for other members to accidentally use directly (without argument checking). Also, it would have needed to take all the same arguments as Filter instead of having them just be in scope.

Note: In Preview 4, local functions must be declared before they are called. This restriction will be loosened, so that they can be called as soon as local variables they read from are definitely assigned.

Literal improvements

C# 7.0 allows _ to occur as a digit separator inside number literals:

var d = 123_456;
var x = 0xAB_CD_EF;

You can put them wherever you want between digits, to improve readability. They have no effect on the value.

Also, C# 7.0 introduces binary literals, so that you can specify bit patterns directly instead of having to know hexadecimal notation by heart.

var b = 0b1010_1011_1100_1101_1110_1111;

Ref returns and locals

Just like you can pass things by reference (with the ref modifier) in C#, you can now return them by reference, and also store them by reference in local variables.

public ref int Find(int number, int[] numbers)
    for (int i = 0; i < numbers.Length; i++)
        if (numbers[i] == number) 
            return ref numbers[i]; // return the storage location, not the value
    throw new IndexOutOfRangeException($"{nameof(number)} not found");

int[] array = { 1, 15, -39, 0, 7, 14, -12 };
ref int place = ref Find(7, array); // aliases 7's place in the array
place = 9; // replaces 7 with 9 in the array
WriteLine(array[4]); // prints 9

This is useful for passing around placeholders into big data structures. For instance, a game might hold its data in a big preallocated array of structs (to avoid garbage collection pauses). Methods can now return a reference directly to such a struct, through which the caller can read and modify it.

There are some restrictions to ensure that this is safe:

  • You can only return refs that are “safe to return”: Ones that were passed to you, and ones that point into fields in objects.
  • Ref locals are initialized to a certain storage location, and cannot be mutated to point to another.

Generalized async return types

Up until now, async methods in C# must either return void, Task or Task<T>. C# 7.0 allows other types to be defined in such a way that they can be returned from an async method.

For instance we plan to have a ValueTask<T> struct type. It is built to prevent the allocation of a Task<T> object in cases where the result of the async operation is already available at the time of awaiting. For many async scenarios where buffering is involved for example, this can drastically reduce the number of allocations and lead to significant performance gains.

There are many other ways that you can imagine custom “task-like” types being useful. It won’t be straightforward to create them correctly, so we don’t expect most people to roll their own, but it is likely that they will start to show up in frameworks and APIs, and callers can then just return and await them the way they do Tasks today.

Note: Generalized async return types are not yet available in Preview 4.

More expression bodied members

Expression bodied methods, properties etc. are a big hit in C# 6.0, but we didn’t allow them in all kinds of members. C# 7.0 adds accessors, constructors and finalizers to the list of things that can have expression bodies:

class Person
    private static ConcurrentDictionary<int, string> names = new ConcurrentDictionary<int, string>();
    private int id = GetId();

    public Person(string name) => names.TryAdd(id, name); // constructors
    ~Person() => names.TryRemove(id, out *);              // destructors
    public string Name
        get => names[id];                                 // getters
        set => names[id] = value;                         // setters

Note: These additional kinds of expression-bodied members do not yet work in Preview 4.

This is an example of a feature that was contributed by the community, not the Microsoft C# compiler team. Yay, open source!

Throw expressions

It is easy to throw an exception in the middle of an expression: just call a method that does it for you! But in C# 7.0 we are directly allowing throw as an expression in certain places:

class Person
    public string Name { get; }
    public Person(string name) => Name = name ?? throw new ArgumentNullException(name);
    public string GetFirstName()
        var parts = Name.Split(" ");
        return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name!");
    public string GetLastName() => throw new NotImplementedException();

Note: Throw expressions do not yet work in Preview 4.


  1. Anything regarding design by contract?

    • James

      Would also love to see this, but don’t hold your breath. They’ve made it significantly difficult to use in the current state with the CodeContracts package/tools. No idea why they aren’t making that with a better syntax part of the language.

      • Nothing on design by contract this time around, and I’m not sure if there will be anytime soon. We’ve looked a lot at contract-style features, and they tend to get quite verbose and complicated. I am not sure that they would carry their weight in added value as language features. But maybe, one day, if we can get the design right.

        While people do use CodeContracts for many things, the 90% case seems to be dealing with null. We are eager to tackle the language integration of that in a more type-system-oriented way, allowing you to distinguish between nullable and nonnullable reference types and track correct usage based on that. I hope this can happen in the next major release of C#.

        • Craig

          More than anything else, you could make me happiest if the next version of C# has support for non-nullable references. I’ve been waiting for that for years… if I remember correctly, it was in a research language, perhaps Cω at one point. I followed Github and at one point it was being talked about for this version, but it seems to have been pushed back. I’d be absolutely fine if this is the one and only feature that makes it into the language. That said, I’m not sure that C# language support is enough to make this a successful feature. It may require changes to the CLR runtime as well. But it would be worth it. As we all know, NRE are the single most costly bug in all software development. While I may not follow the Github discussion as much anymore, please count my vote for non-nullable reference types.

          • Jiri

            I vote for non-nullables too ! 🙂

          • Marek

            Exactly! I used non-nullable types in Spec# when I was working on Microsoft Singularity project and I miss them a lot. Definitely something I would love to see in C# in the future as this would greatly help with avoiding NREs without sprinkling your code with if statements everywhere.

          • MuiBienCarlota

            Non-nullable references were mentioned for .Net 1.2. They disappeared after the postponement of this version and its rebirth as a .Net 2.0 more than one year later.

            They was also implemented in spec#, a research only sharp language.

            All these efforts show that it is important. I’ve always be fan of & and const & in c++ and I was sorry to lose it in C#…

          • Farzad E.

            I don’t think you’re alone in this Craig.
            I remember voting for this feature almost 5 years ago and back in 2012 it was one of the top most requested features on UserVoice and it was one of the most awesome features of Spec#.

            I checked on it now and it is THE #1 most voted for feature request on UserVoice for C# language right now (see: https://visualstudio.uservoice.com/forums/121579-visual-studio/category/30931-languages-c-).

          • Max


        • John Ludlow

          I think you almost had it nailed with Spec#

          public string GetFirstName(string fullname)
          requires !string.IsNulOrEmpty(fullname)
          ensures !string.IsNullOrEmpty(return)
          return string.Split(” “)[0];

          It was something like that anyway. But yaaaay tuples! That’s my favourite part of this whole thing.

        • Very, very, disappointing. We lean very heavily on code contracts in our products for debug contract checks – pre-conditions, post-conditions, interface checks, and object invariant. The lot.

          Frankly, I was at a loss for words when one of my colleagues told me that all this would be useless in Core. Imagine the work we now have to do translating all of our hundreds of interface contract checks.

        • Rob G

          I’d like to add another vote on non-nullable references. They should really be the default, but I suspect it may be too late to fix that.

    • wow 10/10 would read again

  2. Jeremy

    Is Microsoft putting an equal amount of effort into VB.NET or do you recommend we switch to C# now to avoid a sinking ship?

    • Chris

      Hasn’t the writing been on the wall for years?

      • What does this mean for my new VB.NET Silverlight application??

        • J

          What? You’re ridiculous

        • James


        • DoryO

          Ha! Turn it into a Pluralsight course.

        • Alex

          it means you’re using outdated technology.

        • Jon

          Or my .NET Core application.

        • Jose

          chris is hilarious!

        • Carlos Villegas

          Haha nice joke 🙂

        • Is this a serious question?

        • AspNyc

          It means you’re riding a cart and buggy in the age of electric vehicles.

        • Shimmy

          Just as Silverlight, VB.NET is also on its way to the graveyard lol, you and Jeremy are a perfect couple haha.

        • HAHA
          Just as Silverlight, VB.NET is also on its way to the graveyard lol, you and Jeremy are a perfect couple haha

        • Funny or not for some people, but Silverlight can still be used in Microsoft products such as CRM solutions to this day 🙂 regardless good joke…

    • crossslide

      I don’t know what amount of effort Microsoft is or isn’t putting into it, but if you’re willing to look through GitHub issues, you can follow the progress of VB design and implementation there at https://github.com/dotnet/roslyn/labels/Language-VB

      • That’s exactly right. There aren’t as many VB features ready to go in Preview 4, so the VB blog post will come later.

    • Please please please stop ask for anything related to VB.NET. Just let die. If you can’t live without it, maybe it’s time to open a restaurant?

      • Mike C

        …but the very existence of VB.NET makes C# stronger, and vice versa, as features cross-pollinate. Letting VB.NET die would only serve to weaken C# in the future.

        • @Mike C,

          Don’t forget F#! The diversity of languages on .NET has always made for a more powerful platform.

      • Please please please keep asking for things related to VB.NET. As the program manager for Visual Basic it’s absolutely critical that I get feedback from my customers–Visual Basic developers–on the scenarios and technical challenges that matter to them most. It’s my favorite language and I want to keep it a language for success for the customers that love it as much as I do. If there’s a feature or capability you feel you can’t live without, drop us a line on https://github.com/dotnet/roslyn or send me a tweet @ThatVBGuy!

        • You’re our champion Anthony. Keep the flame alive!

          • Claudio Friederich

            Though not essential, genuine out parameters (i.e. an Out modifier to complement ByVal and ByRef) would be great in VB. The reason is that components with methods that use Out parameters use ByRef parameters in VB instead, which means you are forced to initialize variables passed to these parameters to values that will never be used to avoid the “Variable _ has not been assigned a value, a NullReferenceException could result at runtime” warning. Yes, you can turn that warning off. Yes, you can ignore that warning. But that is like the fire alarm that always has no batteries or that goes off each time you turn on the stove. A genuine out parameter offers no new capabilities, but it does give a nice clean way of saying “yes, the variable is uninitialized, and no, this will never matter in this case.” But more importantly, it makes VB-built components better to use from C#, because C# users will not have useless ref parameters that must be needlessly initialized, just because in VB you must use ByRef or ByVal.

        • Claudio Friederich

          I realize that this would be a large feature to implement, but it would be a big winner I think, and in keeping with the unique capabilities of VB.NET. While I have (for many reasons) never liked the REST paradigm which made JSON so popular as a replacement for SOAP in Web Services, JSON in and of itself is another story. It offers advantages over XML, like a true array construct, and the open/close brace is shorter than the open/close tag, and Visual Studio is embracing JSON more and more, like it did XML since the beginning. So, how about 1) a native Linq-to-JSON framework, i.e. JElement, analogous to XElement, similar to what NewtonSoft (www.newtonsoft.com/json) offers, but as a native part of .NET, and 2) JSON literals in VB code, like the XML literals supported for several versions (which I use all the time, in nearly every project), and corresponding VB extension methods for reading JSON object properties, querying for descendant objects, etc., similar to Linq-to-XML?

        • CraigMax

          Thanks for this!


          Your one VB customer in Africa

          Sent from DCOM via MTS

      • Completely agree. VB.NET must die, because it is a complete waste of human resources. After that it would be good to focus on slowly killing JavaScript by replacing it with C# running in limited functionality mode. Web browers could check C# code to make sure that all methods are allowed and compile it on the client side. I really would like for cross-platform browers to use Mono and start supporting this tag on cliend side:

        Imagine posibilities. It would be so easy to extend it by just unlocking current libraries of C# on the client side. For example various math libraries which are safe to use from security point of view.

        • Tag I was talking about was
          «script type=”text/csharp”»


        • “Yes, when you also have the Keys of Barad-dûr itself, I suppose; and the crowns of seven kings, and the rods of the Five Wizards, and have purchased yourself a pair of boots many sizes larger than those that you wear now. A modest plan.”

          • Christopher Bordeman

            The next HTML spec is supposed to include a bytecode substitute for Javascript, allowing any language to be used. So no «script type=”text/csharp”» but a “binary/bytecode” option where you compile C# on the server. So in the next 5 years C# in the browser could be a reality.

          • Holf

            “Hardly one in which your help is needed!” 🙂

          • @Christopher Bordeman there’s already a fair level of support for running C# in the browser today with projects like JSIL, Bridge.NET, and several others I never knew of when i was googling for these names.

        • Néstor Sánchez A.

          Your dream may become true with Web Assembly, which is a low level web scripting language intended to be a target for high level language compilers in the hope of doing best that javascript.

        • Jordan

          ES7 now their updating JavaScript every year I actually starting to like the idea of keeping c# out of frontend

        • LaRell Nielsen

          While compiling C# for client side consumption would make sense from a .NET point a view (and laziness), have you looked at TypeScript? If you are wanting something that allows you to do exactly what you are talking about this is what you can do today and based on the trajectory of TypeScript it will only get better in the future. This would allow you to have the OOP style programming with the check and it does the hard work for you of generating the JavaScript that can be used in all browsers today.

        • cxmu

          There are already several C# to Javascript transpilation projects, the most noteworthy of which is http://www.bridge.net
          It has some kinks, but I’ve already used to to write several small applications without any major problems.

          • It’s amazing for me to have a web site, which is valuable designed for my knowledge.

            thanks admin

        • Dean Kuga

          Completely agree with you on both points, especially on JavaScript which is spreading like a cancer in a form of numerous frameworks being released almost daily now forcing developers to give up on all the best practices of OOP, strong typing and software design we worked so hard on over the last few decades…

        • Wayne

          Better yet, one of you c-sharts could conquer your insecurities and accept that there is more than one development language in the world. Just imagine what you could do with your day if you weren’t constantly fretting about what languages other people were writing in and demanding that reality be warped to your unilanguage mindset! You might even be able to learn a second, or even a third language, just like the grown-up programmers do! Then you could go proselytize to the rest of the c-shart community and make the world a better place!

        • There’s an important lesson here: never use irony in comments on MSDN blogs.

        • AliReZa Sabouri

          haha !! VB die !? why …
          just make a xml document in both c# and vb and feel the power 🙂
          or vb support property with parameters and c# don’t ..
          vb is easy to read
          and and and …
          maybe they should let c# to die.

        • Cyberdyme

          More chance of Javascript being more main stream then C# in 10 years from now..

      • Dr. Obvious

        C# is for people who like writing complex code that’s hard to read, write, and debug. VB.NET is so much simpler and easier to keep bug free.

        • Costea

          c# is for people who like writing code so much simpler than VB.NET

          • Patrick

            working in both VB and C# on a daily basis i can say they are pretty much the same, although the VB lambda syntax is a little verbose. I like the C# syntax more but when working with both you will see they are pretty much similar.

    • King

      You should seriously consider switching to C#. It’s really not that hard to learn and once you do, you’ll wonder why you didn’t switch earlier. It will also give you more weight when looking for jobs. Very few employers are looking for VB.Net developers. I used to be VB 3 and VB 6, then VB.Net, and decided to give C# a try and it was so similar to JavaScript in it’s syntax, that it was really easy to get up and running.

      • Carlos Villegas


        • I programmed in VB (classic) for 16 years. I started in .NET using VB.NET for the first few years but find C# to be superior for its terse syntax. I hate semi-colons but find that overall since the feature sets are nearly identical I would rather read and write less code. The learning curve was simple since there are numerous sites that tell you the C# keyword/syntax for its VB.NET equivalent. I also find many more samples and open source projects in C#. I loved VB (classic) and had the syntax remained closer to its roots VB.NET may have been a good upgrade. Instead it was a completely new animal.

    • @Jeremy,

      If I can read between the lines I think you’re asking “What’s New in VB 15?”. Good question. We’ve been working on VB 15 at the same time but didn’t get it in in time for Preview 4 (which is the topic of this post). Tuples, a story for consuming ByRef returning methods and properties, pattern matching/type-case/select-case-on-type are all in the works. And we’re working with an open source VB developer who’s trying to contribute a feature. We’ve never added everything we do for C# to VB or VB to C#. That’s not how language design works. So, for example VB.NET has a much stronger starting position with lambda expressions than C# (VB already supported iterator lambdas) did so local functions would have more overlap. The actual back-compat concerns with pattern matching and the design in the two languages is different because of differences in Select Case and switch. The way the languages handle ByRef arguments is different so there are consequences there. There were features in VB14 that weren’t in C# 6 and features in C# 6 that weren’t in VB14. It would be a mistake to attempt to measure the capabilities or future of either language based on whether they always copy each other letter for letter.

      But the point is taken, you’d like a post on the topic. I’ll get on that.

      • Jeremy

        Thanks! It would be great to make a post explaining to people that VB.NET is not VB6. I personally prefer VB.NET over C# because it’s equally powerful and much easier to read and write. I don’t understand why VB.NET gets so much hate, except perhaps that everyone associates it with VB6. Let’s rename VB.NET to C#+.NET! 🙂

        • Arwin

          VB is a fine language in isolation, and it’s select case implementation alone almost makes it a superior development language on the Windows platform ;). It’s just that almost all the other currently big languages out there (C++, JavaScript and Java) use the C syntax, and that is why C# is vastly more popular.

          • Chidex Josh

            Seriously I don’t know why some developers hate Vb. Net.
            Pls Vb team should make this clear to the general public on the fact these two languages Vb. Net and c# are equally the same… Just syntactically different nothing more.
            And Vb. Net is also as powerful as any other language can be.
            I love Vb. Net

        • Usually I don’t read post on blogs, however I wish to say that this write-up very compelled me to check out and do so!

          Your writing style has been surprised me. Thanks, quite nice post.

      • @Anthony

        Thanks for the insightful and constructive response.

      • es

        Im also one that prefers vb.net syntax and will continue to use it if I have a choice in the matter.

      • At one time Microsoft promoted the idea that VB and C# would be feature matching and complete as a goal. Is this no longer the case?

  3. Chris

    Wild cards look a little off to me.

    Is there any reason why null is not used instead?

    p.GetCoordinates(out int x, out int y); // Don’t ignore
    p.GetCoordinates(out int x, null); // Ignore return
    p.GetCoordinates(out int x, out null); // Alternative ignore return

    And in the cases where there are overloads:

    p.GetCoordinates(out int x, (int) null); // Ignore return for overloads
    p.GetCoordinates(out int x, out (int) null); // Alternative ignore return for overloads


    (var myX, *) = GetPoint();
    (var myX, null) = GetPoint(); // Ignore

    • Robert P

      I hope they consider what this would do for refactoring and “find all references”.

    • I agree that out null looks and reads better than *.

      • Cristian

        I disagree

        • Ben Gazarra

          F null. Seriously, the language should be doing away with nulls everywhere it can. It has in many places, but some places they can’t really… since they started with String being nullable that will never change, but I wish it would. Nulls are the antichrist.

          • null should be abolished.

            An object should represent something that is tangible and within the grasp of senses. Supporting null is like building a closet that you can never ever put anything in. I have no need for such a closet.

          • One day you and the question mark will be friends Ben and Mathieu. You don’t know it yet, but you will reach that point.

            And then they will introduce tri-states 😀 Variable has value, Variable is null , Variable is awaiting Value :)’

          • Ioannidist


            An object, always represents something tangible. ‘Null’ is assigned to variables, not objects. A variable may or may not hold (point to, refer to) an object.

            Supporting null is like building a closet that you may or may not put (according to the circumstances and needs) something in it.

            Suppose you have an object hierarchy where one object mayor may not “have” a reference to another object (and that’s perfectly normal). For instance a “Person” object may have, or may have not an “address” field which corresponds to an “Address” object with many fields (street, number, city, postal code etc).

            How would you represent a “Person” without an address if you don’t nullify the “address” field?
            Would you create a “dummy” address object in order to represent an absent address for that “Person”? In that case you go against your own words “An object should represent something that is tangible and within the grasp of senses”. Because you would have an “Address” object that would not represent something that is tangible and within the grasp of senses. It is an object that represents it’s own absence.

    • John Stewien

      Is there somewhere we can vote up using null instead of *?

        • Craig

          The problem with _ is that _ is a perfectly fine name for a variable. Perhaps not a best practice, but certainly legal. Also, regarding null, “int @null = 5;” too is valid. “(var x, var @null) = GetFoo();” should be legal. Perhaps without the @, null alone could be made to mean “don’t care”, but the design is questionable in my opinion. int * = 5; is not valid, nor is int @* = 5;, so * seems to be a fine choice.

          • But _ has never been legal in this position:

            int.TryParse(s, _);

            because to compile it would need the out prefix. Therefore _ or indeed any variable name would be fine as the wildcard specifier.

      • Jarosław Jaskułowski

        Wow, that was my first thought too. Null is completely fine. Like /dev/null is on linux.
        Btw. What about pipe-line operator?

    • Julien Couvreur

      Interesting idea. The two main options that were discussed so far were * (star) and _ (underscore).
      Personally, I like _ (underscore). I think null would be a bit confusing, as it suggests passing a value.
      There are a few contexts where wildcards could be used and that need to be considered: out vars, deconstruction declarations, pattern matching.

      However, feel free to offer the suggestion and rationale in the comments on the last design notes on wildcards:

      • Oli

        _ (Underscore) will sit well with the F# fans

        • Just want to add that _ already is a valid identifier in C#, so trying to make it also a wildcard in a compatible way would be difficult.

          Personally I want to say that it didn’t take me long to warm up to * in this capacity. 🙂

          • Andres G. Aragoneses

            Given that * is chosen because _ can’t be chosen, it reinforces the idea that it’s a bad decision, ultimately a hack. Especially considering it clashes with unsafe C# pointer syntax…

            Why don’t you deprecate _ as a valid identifier in C#7 (raising a warning if used), and introduce wildcard identifiers with _ in C#8? You could even make the compiler not accept them if there is any variable named _. So just let _ wildcard identifiers be used by people that have already opted out of using _ as an identifier.

      • kubels

        Maybe void?
        p.GetCoordinates(out int x, out void);
        Its means rest of variables goes into emptiness.

        • LM

          I second this!

          • McNerdius


        • Paul


        • Robert Denk

          Ditto. “void” definitely looks to me to be the best option here. My 2nd choice would be “null”. But “*” does not fit with the style of C#. Also, it doesn´’t make any sense to call it “wildcard” since for me, wildcard means “any value/variable”, while in this context it means “no value/variable”.

          • Precisely my opinion.

        • Hotdog

          I agree with using ‘void’. It fits with the existing usage of this keyword : no output.

          The ‘*’ token is already used for multiplication. Granted that it wouldn’t be the first case of the same keyword being used with different meaning (I’m looking at you, ‘using’), but why do it if another keyword fits near-perfectly?

          Besides, if it’s to lessen verbosity, I’d say minus ‘-‘ would probably be better than ‘*’ to avoid confusing its intent with that of a greedy wildcard from patterns and regexps.

        • Andy

          I really like this option, even better would be to omit the out keyword before void

      • ThoMey

        I agree with Dennis_E, relating to ‘null’, ‘void’ or ‘_’.

        But wildcards?

        To ignore an out variable, you plan to allow “wildcards” like
        p.GetCoordinates(out int x, out *); // I only care about x
        but including the Keyword out.

        As for out variables, you plan to allow “wildcards” in deconstruction like
        (first, *, last) = LookupName(id2); // I only care about first and last
        but excluding the Keyword out.

        It seems to be a little bit confusing…

        What does the wildcard mean? I don’t care about the (always?) back coming value.
        I want the value to be destroyed.
        So, what about using the tilde as in destructors?

        (first, ~, last) = LookupName(id2); // I only care about first and last
        Readable as “Take first, destroy middle, take last”.
        p.GetCoordinates(out int x, ~); // I only care about x
        readable as “Take x, destroy whatever comes next”

        • This is a good option as well – this or void either have existing language meaning behind them that makes it read well.

    • Dennis_E

      ‘null’ looks really confusing. ‘int’ is not a reference type, so ‘int(null)’ or ‘out (int)null’ looks really wrong. Even simply ‘null’ looks wrong in this case (and is potentially ambiguous). Passing ‘null’ where the method is expecting an ‘int’ just looks very wrong.
      Also, ‘null’ is a VALUE and we’re passing in a VARIABLE. It has a different meaning.

      For the same reason, ‘void’ looks weird, too. It’s a type, not a variable.

      I never understood the appeal of _
      It is only considered because some other languages use it.
      Besides, it already is a valid identifier, so it would be problematic.

      * clearly looks like a wild card to me.
      It has to “look off”, because it is special. Wild cards are new to the language; it needs a new symbol.
      I don’t see a problem with *

      • ThoMey

        But I see a problem, because ‘*’ is not a new symbol.
        If you see something like this:
        unsafe static void DoIt(out int* x, out int* i) { /*…*/ }
        DoIt(out y, out *)
        could be confusing…

    • chris

      Or leave it blank or even better no second argument in the tuple literal (though that may mess with overloads).

      So, I would rather see:

      (var myX, ) = GetPoint();


      (var myX) = GetPoint();

      I agree though null is better.

    • Kat

      I agree that the * seems wrong. I propose “..”, something that is used in other languages as a range designator.


      p.GetCoordinates(out int x, out .. ); // I only care about x
      (var myX, ..) = GetPoint();
      var (first, .. , last) = LookupName(id2); // I only care about first and last

    • It probably isn’t null. I imagine that the current * design would create invisible locals that are passed just regularly but not used anywhere. If you would be passing null, that null would appear on the inside of the method with that out parameter. And having null as an out parameter is pretty ugly… You can’t test it and you can’t write to it. out parameters are probably comparable with references in C++, not to be confused with pointers. Pointers can be null, references not. null is definitely wrong, if my assumption of the implementation is correct. After all, this is just a language feature, the CLR must remain unaware of it.

      Anyway, I share the dislike for that * character in the code. An ellipsis (…) is probably not much prettier, too. (BTW, you can write three dots or one … ellipsis character.)

    • Dman2306

      I don’t like the idea of using null. One reason is, if someone (badly) changes the method, your code would “work” where as * would error. Consider:

      void GetSomething(out string blah) { … }

      Say someone changed that to:

      string GetSomething(string prefix) { … }

      Now I agree, it’s bad to change a public interface like that. However, we all know it happens daily.

      GetSomething(*) will fail to compile. GetSomething(null) would “work” passing null as the prefix. I could support “out null” but not “null” for this reason.

    • Cody

      I prefer the wildcard. The null being passed in makes me think I’m passing in null to a method (or it’s a possible default parameter.)

    • James

      I think using a keyword instead of * for wildcard will work better. For example,

      Instead of
      (var myX, *) = GetPoint();

      would be
      (var myX, ignore) = GetPoint();

      in this case the keyword ignore is used to indicate that the developer is not interested in the myX parameter.

  4. crossslide

    I appreciate the efforts to make these features feel cohesive with each other and with the existing language. Tuple types that are anonymous but can have named members are a great feature.

    I’m kind of wary of features that encourage side effects in expressions, or using expression syntax in places that are inherently about effects (e.g., constructors.) For clarity I strongly prefer to keep imperative code in imperative style, and save the expression/functional style for code that is really about values. Of course there’s no way in C# to really enforce or be pure about this.

    • Yeah, I get what you’re saying. C# is rooted proudly in a C tradition, with side effects and results all muddled together in the same constructs (such as function invocation).

      In C# 6.0 we avoided expression-bodied members when things couldn’t possibly have a result (such as e.g. constructors and finalizers), but on the other hand we allowed it for methods even when they didn’t. So that was a bit inconsistent. Some of the new expression bodied members are mostly just filling out that gap, and returning to more linguistic consistency. And if you care less about the purity of it, they are a great opportunity for abbreviating some simple members.

      That said, I think that e.g. the expression-bodied get accessors are neat and useful.

      • I *completely* agree with @crossslide.

        Exactly for this reason I made ReSharper do not suggest to use expression bodies in the case of single assignment inside statement-bodied members and lambda expressions. Side-effects should not be hidden inside expressions if possible. We all know this since `if (x = 42)` disaster in C – assignment expression should really be a statement (and statements have no value).

        And now I’m working on more IDE features to enforce explicit side-effects to be made in statement forms where possible, while you’re making the class members declarations that inherently contains side-effects (constructors, set accessors) expression-bodied 🙂

        While I understand the idea to unify the type member syntax, I don’t understand the idea of introduce even more syntactic freedom in a language 🙂 Especially property declaration (already overly complex), now it may look like:

        1. public string Prop => e;
        2. public string Prop { get => e; }
        3. public string Prop { get { return e; } }

        …all meaning exactly the same thing. And you know developers: if they can do something in a three different ways, they will do it using both of them 🙂

  5. Bob

    Still trying to understand why pattern matching has been introduced to the switch statement..none of the OO developers will use that anyway, maybe in the next few years we might get what scala offers to the community. I like C# but the way its pushing further comparing to some of the other popular languages and in this modern area where more and more we as developers are involved in building distributed applications, pattern matching, records etc would be much more appreciated and will speed up the dev process and the productivity. maybe this sounds rude but in fact that’s the reality which we are facing everyday.

    • Well, we do hope to add a `match expression` to C# in the future, which will be an expression-based, much leaner syntax for switching with patterns.

      But when adding a whole new concept to the language, such as patterns, we think that it’s vital that it fit in well with the existing language constructs. Hence the initial focus on `is` expressions and `switch` statements. We don’t want to glom on some separate functional language to the side of C#. we can (and do) borrow eagerly from functional languages such as F#, but we have to do it in a way that is really deeply integrated into the feel of C#.

      This, by the way, is very similar to, and in no small way inspired by, the philosophy of Scala, which holds that functional and object-oriented programming aren’t like oil and water, but can in fact be blended pretty well. Scala did it from the start, whereas we began in a mostly object-oriented place, and have been trending functional ever since. But hopefully programs aren’t necessarily written in the “object-oriented” or “functional” subset of C#, but instead just good code taking advantage of the full range of expressiveness.

      Now that we’ve found an approach to patterns that does fit super well into existing C#, we can think about where to take it next in terms of a) which other patterns are interesting, and b) which other constructs can we put them in.

      • Do you plan exhaustive type checking (like with f# discriminated unions, and the new switch in TypeScript)? This feature really helps with extending return values types while getting compiler-level confidence that you’ve covered any new return values.

        Also, am I right in thinking that .Item1 etc. will be the names that reflection returns? If so, will there be any way of finding the descriptive names via reflection, or from outside an assembly if they are used on public return types?

        • exhaustiveness: It’s on our radar. There needs to be a way to declare types that have a fixed number of possible values. Some languages do this with discriminated unions, but adding a new kind of type declaration to the language should not be done lightly. If we do – or find some other way of expressing exhaustiveness – then we will certainly take advantage of it by having the compiler warn whenever a match is incomplete.

          Reflection: The user defined names in tuples exist only at compile time. They are exposed in metadata as attributes on the parameters, return values etc. that have tuple type, not inside of the type itself. This turns out to be by far the best representation, both when it comes to efficiency and allowing the flexible equivalence between tuples with different names that we want. But it comes at the price of not being able to check those names at runtime, through reflection, or type checks, or otherwise. They simply aren’t there.

          • Dev

            ReSharper can already give exhaustiveness warnings. We need compiler errors now.

      • endrju

        Thanks for all new features, I’d like more in the future. Please fix the darned IDisposable (automatically call Dispose at the end of the scope if no more references) and maybe amend its design in the way you did with Deconstruct method (no interface, just naming convention). More info: http://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About

        Type inference for parameters and return values would be helpful too.

        Type member constraints so that millions of interfaces with single method are not required anymore (although I think those contraints can be internally implemented as interfaces).

        BCL: for any method that accepts delegate add overload that accepts lambda expression.

  6. J

    What about adding some postfix conditionals?
    e.g. DoSomething() if (a == 1)
    and DoSomething() unless (a == 1)

    • Nira

      use prefix conditionals

      if (a == 1) DoSomething()
      if (a != 1) DoSomething()

      Don’t ask for a feature that does not correlate with the design principles of C#

      • Andres G. Aragoneses

        Seconded. Don’t make C# become Perl please.

  7. Chad Burnette

    Do all these features work in .NET Core?

    • Julien Couvreur

      Yes, they do.

    • Alex

      My guess is that yes, it will.
      Since .Net Core is a library, while C#7 is well, the language itself.

      I don’t see what would break there, since they add features without really breaking some.

      I may be mistaken however, so take this with a grain of salt. Hope it helps.


      • Nira

        It’ll work.

        Languages are independent of frameworks or platform libs as they are from the beginning of the Computer Age

    • Yes. Our general goal for language features is to make sure they work across all our .NET offerings (.NET Framework, .NET Core, Mono, Xamarin etc). However, there are language features that have dependencies on APIs provided by the underlying platform. In many cases, such as tuples, we can get away with providing the functionality out-of-band so you can use new language features on existing platforms without having to wait for all platforms to catch up provide the functionality in the core.

  8. Plácido Bisneto

    why not allow the tuples to be used as if it was a dictionary?

    var x = TupleMethod();

    x[0] == 1
    x[1] == “hello world;
    (for the non-named returns)


    x.FirstReturn == 1
    x.SecondReturn == “hello world”


    x[‘FirstReturn’] == 1
    x[‘SecondReturn’] = “hello world” ?

    I can see some usage for dynamic scenarios for the string one. 🙂

    • Nira

      You can use Dictionary type directly for that scenario

      Json objects can be one thing, but that’s why you have Json.NET

    • We use named properties rather than an indexer because we want to enable strong typing. Indexers imply a universal type for all elements of a tuple, which would generally mean its would be object.

      That being said, there will also be a way to get to the elements in an indexer like way that is untyped.

  9. Bhupendra singh

    Having tuples return type may make the code look more complex but it can help reduce the amount of effort in making out variables which was equally hectic, What is the performance measure using the tuples in the code rather can having multiple out variables ?

    • Good question. The performance characteristic is probably quite specific to the size of the argument and the number of operands. Out parameters essentially require an indirection to write to specific address, so all out variables end up being pointer sized. Tuples are value types that are returned by copying.

  10. Nira

    Please bring in wild cards we don’t have to allocate for the variables we don’t want to right

    It’s a performance standpoint so please do not omit wildcards as they are close part of the feature you are bringing

    You cannot build house without bricks and cement as such cover the necessities and fundamental features first


    • In case of out variables, wild cards shouldn’t have any performance benefits. In IL you’re forced to provide a slot that the calling method can write to. So if you specify a wildcard, the compiler will simply emit an unnamed local.

      • Nira

        I see, so there is no need for wild cards at all?


        • Wildcards are a convenience, not a performance enhancement. They let you say “don’t care” instead of introducing a dummy variable. It is not only shorter, but a clearer expression of intent.

  11. Nira

    And for the tuples please support like this….

    string (first, middle, last) = p.GetName();

    or is it already supported like using var?

    • Matt

      Did you read the post? This exact scenario is covered..

    • No, this syntax is not supported. In general, there’s no reason to expect different tuple elements to have the same type, so we aren’t planning this abbreviation. Note that the `var (…)` syntax can infer different types for each variable. So these three lines all mean the same:

      var (name, age, height) = person.GetDetails();
      (var name, var age, var height) = person.GetDetails();
      (string name, int age, double height) = person.GetDetails();

      • Nira


      • Mark Shapiro

        But one of these is invalid?
        var(firstName, lastName) = person.GetNames();
        (var firstName, var lastName) = person.GetNames();
        (string firstName, string lastName) = person.GetNames();

        string(firstName, lastName) = person.GetNames();

        So you can’t explicitly type the tuple elements to be the same type, unless you type each one of them?

        It’s valid to do string firstName, lastName; so why not string(firstName, lastName)?

        • Steven Fox

          You’re not typing them at the consumption point, the method is, hence var working.
          in this case var would mean ‘accept the type im given’

          whereas string(firstName, lastName) would mean “ensure all of these are strings”

          There’s no other places in c# where types can be inferred or cast in bulk, it doesn’t give any major benefit, so why incur the risk of doing it here?

  12. Aksel

    Tuple elements are counted from 1. Arrays, listis and other collections are counted from 0. In my opinion it’s distracting an unnecessary inconsistency.

      • LOL. I think it’s more that 0-based arrays it a consequent of pointer-arithmetic. 0 is an offset into a data structure whereas tuple elements have ordinals. The 3rd element of an array is at <beginning of array in memory) + ((3 – 1) * sizeof(arrayelement)). It's convenient that for the first element that's 0 and it cancels out all the terms (yadda yadda math geek). There's nothing comparable in the tuple space because each element can be of a different size. All you can say is that it's the first or second or third element. That tells you nothing about where it is in memory, really.

    • Julien Couvreur

      That is a fair point, but our hands are tied by historical decisions. System.Tuple types were introduced in .Net framework 4, which you can use in any .Net language and are used ref tuples in F#, and their first element is called Item1.
      C# tuples are a convenience syntax on System.ValueTuple. It is a strong requirement to keep ValueTuple and Tuple be consistent and as close as possible, so they also must have Item1 as their first element.

      • Aksel

        Thank you for the clarification!

    • They are property/field names, not array indices. You can’t for-loop through tuple items.

  13. It’s amazing. Coding become more easier than ….

  14. All proposed features seem like they’d be great additions! I’d also like to see wildcards. I tend to use _ now, but I could see using * instead.
    I’m especially interested in the generalized async return type feature. Will this mean that IAsyncEnumerable and IObservable could potentially be used as async return types?

    • If you can use _, what would be the difference of using *? From the IL perspective it’s the same.

      • Spetsen

        _ is just a convention for variables you don’t care about, it is not enforced in the language. If another developer is not aware of the convention (or just purely evil) he/she can start using the variable, confusing everyone who is aware of the convention. This developer might not be aware of the meaning of * either, but the compiler makes sure it’s not misused.

    • Generalized async return: yes, in principle IAsyncEnumerable and IObservable could be augmented to be allowed as async return types. We would have to provide builders for them. The only thing those builders could currently do is return single-value implementations, since there is not (yet!) a notion of async iterators.

      That’s something we’d like to look at further for the next version. I think it’s better to wait for async iterators before we consider builders for these interfaces. However, if you want, you can make classes that implement those interfaces, and you can make your own builders for those. It’s not going to be easy getting it right! Stay tuned for more details and a working implementation of the generalized async return types.

      • You should be a part of a contest for one of the best blogs online.
        I’m going to recommend this website!

  15. Ken

    How do the new tuple types work in a dictionary? Will the types gain an IEquatable implementation? Or will EqualityComparer.Default detect a type which inherits from TupleValueType and do something special to use all the fields?

    If so, I hope it does this without resorting to reflection, which arguably ruins the performance of otherwise handy Enum operations like TEnum.HasFlag().

  16. Sinix

    > Deconstruction is not just for tuples. Any type can be deconstructed, as long as it has an (instance or extension) deconstructor method of the form …

    Will same approach work with pattern matching via the `is` expression? Current drafts for PM has an ` operator is(…)` but tuples do use special-named method instead. What are reasons behind that?


    • The `operator is` was an earlier proposed syntax for what eventually became the `Deconstruct` method. They serve the same purpose, which is to describe how an object is deconstructed, and both have potential to grow more expressive as C# evolves (to allow something like F#’s “active patterns”, for example).

      Deconstruction does not yet work in patterns. We hope to get to that soon, but not in C# 7.0. In general, think of patterns as a new concept that has taken root in the language and can evolve over time.

      • Sinix

        Ok, got it.

        As a sidenote, new scoping rules for out vars/is expression are much better. Cudos for that:)

  17. Mladen Mihajlović

    What about switch fall through and goto? How would they work with expressions?

    • Mladen Mihajlović

      Uh patterns not expressions…

      • There are some restrictions:

        * You can only goto a constant label
        * If you have fall through, variables introduced by either label will not be definitely assigned, so they won’t be useful in the body. Consider:

        case string s:
        case null:
        WriteLine(s); // Can’t! s may not have been assigned.

        This falls out naturally from definite assignment analysis (which is a wonderful tool in the language that has helped us at every turn with patterns!)

  18. I’m still hoping this will evaluatie to an nullable int some day:
    var age = isPerson ? 1 : null;
    now you have to choose between a few options that just don’t feel right:
    var age = isPerson ? (int?)1 : null;
    var age = isPerson ? 1 : default(int?);
    var age = isPerson? (int?)1 : (int?)null;

    • Jiri


    • berkeleybross

      At least its a compiler error! In VB, “Dim age = If (isPerson, 1, Nothing)” would be equivalent to “var age = isPerson ? 1 : 0;” Craziness!
      I would love to see nullable inference though 🙂

  19. I consider:

    if (o is int i && p is string s) return string.Format(s,i);

    to be equivalent to:

    if (o is int i && p is string s)
    return string.Format(s,i);
    // I wouldn’t expect i and s to be in scope here anymore.

    So I find this illogical

    public void TypePattern(object o)
    if (!(o is int i)) return;
    WriteLine(new string(‘*’, i)); // I wouldn’t expect i to be in scope here anymore

    • Spetsen

      I agree. The most similar things in C# today would be for and foreach where you could do:

      for (int i = 0; i < 11: i++) continue;
      // i is not in scope here


      foreach (int i in ints) continue;
      // i is not in scope here

        • So you made a tradeoff between:
          – Consistent behavior of scoping
          – The ability to use the ref returns in guards

          I believe I’m not the only one who hopes this tradeoff will be re-evalated. In this case, I value consistent behavior more. In one example one exception is traded for another:

          if (!(o is int i)) throw new ArgumentException(“Not an int”, nameof(o));

          Why not just catch the IllegalCastException?

          You can also view the scope-escape as a different problem, to be tackled seperately:

          if (!(o is export int i)) return 500;
          if (!(p is int j)) return 500;
          // i can be used here, p cannot.

          this can also be used like this:

          export var session = OpenSession():
          // do stuff

          • I know this pseudo code would break existing types named ‘export’.

            And I know session should just be disposable. But it just isn’t always. And there are use cases you want to use variables in you finally and catch, that are declared in you try block. Now you need to:
            var session
            session = OpenSession():
            // do stuff

  20. Solid improvements, team. Looking good! I might actually start using the Try*(out) pattern now. 😛

      • McNerdius

        Try it….. out ? buarhar 😀

  21. Why are tuples mutable? This seems wrong to me. For years, we’ve been told that mutable structs were bad. The existing System.Tuple classes are immutable. And now this new ValueTuple type is mutable?

    • Andy


    • Will


    • The reasons why mutable structs are often bad, don’t apply to tuples.

      If you write a mutable struct in the usual encapsulated way, with private state and public, mutator properties and methods, then you are in for some bad surprises. The reason is that whenever those structs are held in a readonly variable, the mutators will silently work on a copy of the struct!

      Tuples, however, simply have public, mutable fields. By design there are no mutators, and hence no risk of the above phenomenon.

      Also, again because they are structs, they are copied whenever they are passed around. They aren’t directly shared between threads, and don’t suffer the risks of “shared mutable state” either. This is in contrast to the System.Tuple family of types, which are classes and therefore need to be immutable to be thread safe.

  22. What’s the current status on supersede/original/replace and source generators? Any chance that they’ll make it into C#7?

    • Timing-wise, that doesn’t seem likely. The hold-up is primarily making sure that we build a source generator API that is a pit of success from an efficiency standpoint. This needs some bake time.

      At the language level, things aren’t all that complicated. We’ll add the original/replace features when source generators are getting ready to ship. We’re open to doing it in a point release of the language, if necessary. But we don’t want to release them too early, either, since they are being codesigned with the broader source generator feature – we want to make sure that we ship the right thing for the scenario! 🙂

  23. Am I the only one that doesn’t think Tuples are a good idea?
    What’s wrong with a simple private class definition as the return type or perhaps allow methods to return a dynamic object?

    public dynamic Foo()
    return new { First = “Joe”, Last = “Blogs” };

    • dynamic has terrible performance, and by definition, is not type-safe

    • Drew Noakes

      Worse performance, memory usage and no type safety.

  24. Craig

    The syntax for local functions is less than ideal. When I see an unconditional return in a method, I expect anything below it to be unreachable. But with the introduction of local functions, this preconception now vanishes. I suppose one could argue that the local function is not really reachable–and in some strict sense that is true–but it certainly makes the code more difficult to read in my opinion. Can the local function also be declared at the start of a method? Not that that would make the code any easier to read, but at least it does not directly after the method return statement.

    • There seem to be different preferences around where local functions should be declared. Some would like to declare them first, like you outline, and some at the end, after the enclosing method’s return statement, where they are not “in the way” of reading the main flow.

      We will allow both. The current prototype only allows them to be declared before they are used, but we are fixing that.

      There’s some pretty nifty definite assignment analysis going on with local functions, by the way. Getting this right was one of the reasons for the current restrictions in the preview. This has to do with when the local function uses variables and parameters from the enclosing method:

      * We track which enclosing variables the local function reads from. It is an error to call it before those variables are definitely assigned. That way you can’t use local functions to accidentally see uninitialized state.
      * We track which enclosing variables the local function writes to. This lets us know that when you’ve called it, those variables are assigned. That way you can use local functions to initialize your variables, for instance.

    • Drew Noakes

      Finally blocks also violate your assumption that code after a return is unreachable.

    • Mike

      While you can await anything, to mark a method signature with the async keyword (so you can await in it), it must return void, Task, or Task

      • endrju

        Why does the ‘async’ keyword exist at all? Having ‘await’ in the method body isn’t enough to know that it is async? Can we deprecate ‘async’ finally?

        • async does other things than allow awaits. You can write an async method without awaits (though you get a warning).

          More importantly, it is a lot easier to see if a method is async when you have to declare it rather than search for the use of a given keyword somewhere in the body. If we could do it over, we would probably have done iterators the same way – with a modifier on the method, rather than depending on “yield” showing up somewhere in the body.

  25. Ivan

    My thoughts are a bit different. It looks like that C# is becoming polluted with all kinds of tricks. I’m afraid that this could lead to a big ball of mud. It isn’t really necessary for each new iteration of VS to have new language features, or that many of them.

    Don’t get me wrong. Most of this stuff is great and I use a lot of C# 6 features as well and am going to use these too, but the pollution scares me. The language will have better features in the future, but the “obsolete” ones will remain and pollute. Then what? Too many unecessary features that are obsolete and no one uses them, but cannot be removed due to historical reasons. The learning curve for a beginner to the language could rise dramatically.

    I’m just asking have you guys thought of that? Also do you have a longterm plan for the language, i.e. what do you want in C#10 and where do you want the language to go? Or is your goal to switch C# from OO to functional language or a mix of both or a new bread :)?

    • Which language features do you think are obsolete? The only one I can think of is anonymous method using the delegate keyword, which is a bit redundant with the advent of lambda expressions.

    • You hit on something very central to language evolution. We can add, but we can never take away. This weighs heavily on our minds as we evolve C#. Anders famously says that “every feature starts with minus a hundred points”. For every feature we try to think about whether people will appreciate it not only now, but ten years from now. We try to think about whether it’s worth not only the work involved today, but the space it will forever occupy in the language surface area.

      We’re often right, but not always. As you know, the future is one of the hardest things to predict. 😉 And this brings us to another aspect of our design approach: we need to be bold. We need to not be stymied by our responsibility to a distant future. Because otherwise we won’t have that future. C# needs to be among the greatest programming languages today, or it won’t be among them tomorrow.

      So we do add things pretty aggressively. We try to add the most valuable features to developers. Moreover we try to add them in a way the minimizes the “agin” of the language in terms of added complexity. Yes, pattern matching is a new feature, but it works in existing constructs such as “is” and “switch”, and over the existing kinds of types. It is (hopefully) well-integrated with our past. At the same time, it introduces patterns in a way that leaves lots of room for them to grow as a concept, without that generality introducing a tax today. It is well-integrated with our plausible future.

      You won’t believe how much time we’ve spent speculatively designing the possible futures of patterns, just so that we could make sure to remain open to them. This is part of how we try to keep the language’s long term health and viability at heart as we add new features.

      I hope that helps give a picture of how we think about the long term evolution of C#?

      • Ivan

        Absolutely, Mads. That’s the answer I was hoping for!

      • “We can add, but we can never take away.”

        Have you considered taking away? This would obviously brake old code but I think that is not as bad as it might seem. It is possible to develop tools which would migrate old code to new code and those tools could be integrated into VS.
        And even without tools, migration to new code by hand is done once and everything is fine. The amount of work isn’t that much. The amount of work that accumulates from less readability and learning in code that contains legacy code is hardly measurable but i think it exeeds the work of migration.

        Short: Clean code is more important than compatibility to old code.

        • Looking at the Python3 as the not backward compatbile successor to Python2 language (with “2to3” tools support) indicates otherwise. Python3 is around for many and it is still a source of confusion, irritation, and debate.

          • I think Perl is setting up for the same issues in the switch from 5 to 6.

  26. Regarding switch and patterns (as well as other enhancements)…. Unless magic is happening, it seems the switch statement is degrading into syntactic sugar over a set of “if {} else if {} else if {}” rather than the original capability of being a high speed indexed jump table.

    • Jiri

      Look into IL, it has always been if/else if/else if and not highspeed jumptable…. (AFAIK).

        • Ian Marteens

          Last time I checked it, string switchs were using a hidden dictionary mapping strings to integers, and then using the integer values in an integer switch statement.

    • The compiler devs on this feature are very focused on optimal code generation. There are many things you can do to optimize, such as factor out shared tests, reorder, etc. Switches with just constants will continue to be as efficient as they are now, and then as the patterns get more complex, obviously that is going to have a perf impact. But in general, we can make a switch at least as, and often more efficient than the if/else chain you would have had to write yourself to do the same tests.

  27. Nick

    if (!(o is int i)) return

    There should be a new keyword for this:
    if (o isnot int) return

    • That is worth considering. VB has “IsNot”, and people do ridicule it a bit, because of the alternative way you can read that string of characters. But it does sometimes make code more readable.

      Maybe C# should call it “aint”. 😉

      • Yeah. People laughed when we added obj IsNot Nothing so we doubled down on it in VB 14 and added TypeOf obj IsNot String 🙂 If at first they laugh, keep doing it!

        • Tristan

          I very like IsNot, and never use not .. is that looks convoluted comparing to IsNot

      • Or we could avoid adding a new keyword altogether: if (o !is string)

        • McNerdius

          huh, nice !

        • Néstor Sánchez A.

          My vote for that!

        • Andres G. Aragoneses

          Fuck yeah!

      • Mikkel

        I generally dont have a problem with the

        if( !(o is int i) ) return;


        But maybe, if it should be integrated it would make sence with a

        if(i !is int i) return; // note the ! is

      • WillC

        “if (o isNot int) return;” +1 as is the best solution.
        “if (o !is int) return;” I could live with.
        “if ( !(o is int i) ) return;” is clumsy and HARD-TO-READ at a glance.

  28. nockawa

    Is there anything plan to have more control on the immutability of methods/arguments like the const keyword of C++?
    I’ve never understand why it’s still not around, it’s great for the developer to know a method/data can’t be changed by the callee and I’m sure the generated code can benefit of optimization in such case.

    • I agree. Lack of support for designing in immutability into your code/types is in my view the thing that is most obviously lacking in C#, so it’s a shame that there’s no movement on this. Having said that, I suspect it may be hard to add immutability features in to C# without also adding such support into IL, which possibly restricts the C# designers’ freedom in this regard. And there is the issue of proliferation of features making the language too bloated – which I think is already happening, even without support for immutability.

    • We do have features on the radar for that, but haven’t acted on it so far.

      A simple solution is to allow the “readonly” keyword on all parameters and locals. One problem is that when you write in a certain style, ALL parameters and locals should really be readonly. And now you end up with this attractive nuisance of nine extra characters bloating every declaration. It’s an “attractive nuisance”: it makes the world a little better, but better enough?

      A way to reduce the bloat to something acceptable would be to have an abbreviation of “readonly var” to maybe “val” or “let”. That would at least take care of locals that are initialized. Is that a good enough fix to make this worthwhile? Not sure yet.

      • endrju

        Or maybe some kind of a pragma or keyword or modifier that would say ‘everything down below/in this scope is immutable unless marked with “mutable”‘. What do you think?

      • Is there a spot in the plan for a more strict version of the `readonly` modifier on members? Currently, as I understand, `readonly` members can still be modified with reflection, making some performance optimizations by the JIT compiler impossible.

      • nockawa

        A readonly keyword put on a method would be already a great start, then the implem of the method couldn’t modify data members of the object it’s called upon not called non read-only methods. But we would still need a keyword like the C++’s mutable to be able to override this rule has it has been proven a necessary thing (e.g. when you put in a cache the result of a get operation for a faster next get).
        For me immutable methods are really important in the design of your APIs, it should be also supported in the interface declaration.
        Next would be readonly parameters of a method, it’s also important because it’s a great constraint to let the user know about (and I think the compiler could benefit from it to speed things up).
        Last, readonly on local, well I’m not sure there’s a true value out there, it’s really an implementation hint that tends to annoy you at the end of the day because you can easily start to declare many local as read-only and a small change oblige you to remove this immutability on many things. It’s like the const in TypeScript and I really don’t use it, because I think there’s not real value.

        To sum up, it’s all about contract between the API design and the user of the API, such thing lacks a lot for me.

      • Andy

        rvar 😉

  29. Uygar Manduz

    Is it possible to add sepecial keyword to return this class type. We need if we use inherited class.

    public class A
    public this Method1 ()
    // do something
    return this;

    public class B : A
    public B Method2 () {}

    var b = new B ();

    • There’s a fabulous amount of research on “this types” or “self types”. My own view is that they are somewhat useful but

      * Add a bunch of complexity to the type system, while
      * They still aren’t general enough to express many “covariant” patterns.

      The languages that solve this best, in my opinion, are ones that have some variant of “virtual types”, or what Scala calls “abstract types”. That’s really a very expressive mechanism. But realistically I don’t see us trying to embrace that in C#; that would be a massive effort down through the runtime, for not enough benefit.

    • Ståle Kvernes

      Isn’t this solvable with:

      public class A : where T : A
      public T Method1()
      // do something;
      return this;

      public class B : A
      public B Method2()[}

      var b = new B();

      • Ståle Kvernes

        the $lt; disappeared

        public class A<T> : where T : A<T>
        public T Method1()
        // do something;
        return this;

        public class B : A<B>
        public B Method2()[}

        var b = new B();

        • You actually make it seem really easy along with your presentation however I find
          this matter to be really something which I believe I might never understand.

          It seems too complicated and extremely wide for me.
          I’m taking a look forward in your subsequent submit, I’ll try to get the dangle of it!

  30. Loving some of the enhancements. I’m a little uncomfortable with deconstructors being a method, although it does allow it to be called outside of deconstruction, this is not necessarily a good thing. I’d personally prefer it being a special case, such as constructors, and finalizers. The main reason being to make refactoring easier – for example, it’s not obvious that renaming the method would break any Deconstructing assignments and/or declarations – particularly in 3rd party libraries.

    Also, rather than returning void and using out parameters, why not make use of the Tuple return syntax itself, which is less verbose and clear.

    You could use the class name, as methods are not currently allowed to share the name of the class (to prevent ambiguity with constructors) so if you use a ‘constructor’ with a tuple return type, this is easily disambiguated by the compiler, and produces a very clear and succinct syntax:

    class Point
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public (int x, int y) Point() => (X, Y);

    Which I think is significantly better than the proposed:

    class Point
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y) { X = x; Y = y; }
    public void Deconstruct(out int x, out int y) { x = X; y = Y; }

    • To further expand on my objection to the current syntax, I’ve been racking my brain for examples where classes have features introduced to support new syntax.

      1. Constructors/Finalizers which is where I’ve suggested Deconstructors could/should live.

      2. Operators – this is a possibility, but is more verbose e.g.
      public static (int x, int y) operator Deconstruct(Point p) => (p.X, p.Y);
      Though, what would explicit operators mean (or do just disallow them)?

      3. Interfaces (e.g. ‘using’ support of IDisposable) – not applicable as the signatures necessarily need to change.

      4. Extension methods – again possible, but I don’t like and what do you call the method? You could use ‘~’ perhaps or ‘Deconstruct’ (but the linking would then be magic as with the current preferred syntax)? e.g.
      public static (int x, int y) ~(this Point p) => (p.X, p.Y);

      Of course, the 4th option is the only one where you can also call the method directly, whereas 1 & 2 do not expose methods on the objects, which I believe is preferable – just as you can’t call the operators directly.

      In all cases, the syntax at least tries to indicate to the developer that something special is going on…

  31. I already love out variable 🙂 except the usage of * for any.
    * means pointer, especially in a parameter context.
    Why not “,out any” or “, out unused” or even just “,out”

    • Mac

      Somebody else suggested “void” which was the first suggestion I’ve seen that really sounded right to me.

    • Mike

      Out of curiosity, what do you have against partials?

      • I have nothing against them per-se. I just would rather design my code without having to start using partials just to do source generation.

    • Source generators will not be in C# 7.0. We hope to do them after, but any guess about when exactly would be speculation at this point: we are actively working on them, and we will ship them – and the associated language features – when we get them right. 🙂

      • With havin so much content do you ever run into any problems of plagorism or copyright
        violation? My website has a lot of exclusive content I’ve
        either created myself or outsourced but it seems a lot
        of it is popping it up all over the web without my agreement.
        Do you know any methods to help reduce content from being stolen? I’d truly appreciate it.

    • I see the way we design the language pivoting a little. Or an inversion of control, so to speak. It’s not that the version number decides when a feature shows up, the feature reaching readiness will decide the version number (major or minor). For a feature with the kind of potential impact that source generators could have we don’t want to rush them and fail to fully explore the design space because of a deadline. I want the community to have the right amount of bake time to use the features and help us find the sweet spot. The best way you can help us get the best features into C# and VB faster is by participating in the design discussions on GitHub, downloading the prototypes and feature branches, and just throwing your most creative uses at the features. We’ve done a lot of work in Roslyn to make sure you aren’t just limited to using features when we snap them to a preview, you can get the sources for the features as we’re developing them. Long before there’s any official “C# 7 + 1” VS beta. And it’s going to be that community participation, I believe, that drives most the language evolution rather than a particular version number or release schedule.

      Thanks for paying attention on GitHub and continuing to ask us about this. Keep up the good work!

  32. idoby

    Why introduce both out variables and tuple return/deconstruction? Programmers designing functions that “return” multiple values would have to pick one over the other and IMO returning a tuple is shorter, clearer and provides more opportunity for optimization (with out parameters you have to emit load and store instructions because the reference passed in might be aliased elsewhere and accessed from another thread).

    Is the introduction of out variables meant just to simplify programming against existing code that uses out parameters?
    The added convenience might encourage programmers to use out parameters more often.

    • Yeah, that was a bit of a dilemma for us, but we ended up believing both have a place. We think that in most cases people should use tuples for multiple results. There are some cases where that is not a good idea:

      * when you want multiple overloads with different sets of result values: you cannot overload a method on return type. (That is the reason why the “Deconstruct” method used by deconstruction takes out parameters instead of returning a tuple)
      * when you implement the Try pattern you want to just return a single bool, so that you can write the call in e.g. an if condition. You want additional results to come through out parameters instead.

      • idoby

        Thanks for replying. Those are fair points.
        I’m not sure why I’m so opposed to out vars. Maybe this is the effect lots of bad C++ had on me. 🙂

        Anyway, thanks for your awesome work on C#!

  33. Patrick

    I like a lot of what we see in the tuples feature. However,

    “Generally you can assign tuple types to each other regardless of the names: as long as the individual elements are assignable, tuple types convert freely to other tuple types. There are some restrictions, especially for tuple literals, that warn or error in case of common mistakes, such as accidentally swapping the names of elements.”

    That means that we’re really getting that Item1 Item3 nonsense. Guess what you’ll get at reflection time? Throwing away useful type information at runtime is a java-level mistake. Why can’t (name, age) be a type whose properties are name and age, like the developer intended? Item1 Item3 guarantees ordering misunderstandings.

    “Tuples are value types, and their elements are simply public, mutable fields. They have value equality, meaning that two tuples are equal (and have the same hash code) if all their elements are pairwise equal (and have the same hash code).”

    Mutable value types, encouraged to put into dictionaries. Absolutely insane.

    I’d much rather tuple types like (string, string) and (string name, int age) be the “names” of the anonymous types we already have. What we actually want is short hand for objects that have a known set of name/type/value triplets. Caring so much about the order of items is just “programming by coincidence”.

    • There are a number of approaches we could have taken to tuples, each with their own pros and cons. We do recognize that the loss of names at runtime is a downside, but the cost of keeping them would have been prohibitive. As it is, we can generate all tuples to a small fixed set of predefined types, rather than emit many new type declarations whenever tuples are used (or carrying the names as part of the tuple’s runtime state).

      Our mental model for the tuple design was analogy with parameter lists. After all, their primary use case is as “return lists”. Just as with parameter lists, the order is what matters, not the names, but you have the names for clarity purposes, so you don’t get things mixed up accidentally.

      “Mutable value types, encouraged to put into dictionaries. Absolutely insane.” That kind of statement would probably benefit from being accompanied by some sort of argument? 🙂

      • Mark Shapiro

        Implementing tuples as you have makes more sense in the context of anonymous types, if you also permitted passing of anonymous types as parameter and/or return values. For example, given something like:

        {string BP, int Pulse, double Temp) GetVitals() => new { BP = $”{Systolic}/{Diastolic}”, Pulse, Temp };

        you could call it like:
        var vitals = GetVitals()

        or even (using the Tuple syntax to deconstruct the anonymous type)
        var (bp, pulse, temp) = GetVitals();

        This becomes a bit more relevant in applications which make heavy use of LINQ. I’m constantly writing LINQ queries which return anonymous types, but then if I need to return the result to a caller, I have to declare an explicit type. Tuples deal with this partially, but the loss of RTTI can be a pain.

      • I guess Patrick’s comment about mutable types in dictionaries was about using them as keys, so if a key is mutated then the dictionary is effectively corrupted.

        But that does not apply with tuples as they are value types, so once stored in a Dictionary as a key, it is only possible to obtain a copy. There is no way to “reach inside” and mutate the Dictionary’s on copy.

        The real trouble would start if KeyValuePair had a property ‘ref TKey KeyRef’ but I guess that’s not on the cards!

        Would be great to see ‘readonly’ allowed in more places.

        It would be great to have immutable record types with non-destructive mutation, perhaps similar to object initialisation.

        var p = new Person(“Homer”, “Simpson”);

        var p2 = p { Name = “Bart” };

  34. Joshua Ellinger

    Although I like and expect to use a number of the features, my initial reaction is that no one is acting as a gate-keeper on the language.
    It feels like there is a “let’s do everything” attitude rather than thinking about how to make a simple coherent set of features.

    I’ve done a little work in GoLang and it is refreshing to have a focused sharp tool rather than a Swiss Army knife. It is a little too simple but it reminded me of the cost of having so many language features.

    At this point, I think it would better serve the .Net community if they froze C# language syntax and made another language (C-flat ?) where they could start clean. But that goes against Microsoft’s culture so strongly that I don’t see it happening.

    • See my earlier comment on language evolution. It’s really a question of philosophy. We lean in the direction of evolving the language as the world and the developer base evolve. That’s not going to be to everyone’s taste. Believe me, we do try to be discerning about what we put in the language, but we do tend to favor day-to-day developer productivity over linguistic purity if and when we have to choose.

      • It feels like C# is becoming Scala on .NET.

        As a long time C# programmer, that’s quite cool – I have all these new tools and ways of solving problems.

        It does make C# increasingly more difficult for beginners though. I try to imagine what it would be like learning to program C# today. There is _so much_ you’d have to learn just to understand the syntax… before you even begin the process of mastering how to structure your code, projects and solutions, test strategies, builds and deployment. And then, if you’re on the web, you have to do the front end using a whole different set of technologies for all of that!

  35. What happend to primary constructors? (postponed in Version 6)

    • The way we had them for C# 6.0 wasn’t good enough. They are still on the radar, along with the related concept of record types (which we considered for C# 7.0), and I am hopeful that we can land on a better design – maybe one that encompasses both.

      • “sitll on the radar” for version 7.0?
        Or is it already postponed to a later version?

  36. Some great new features – I’m going to love the ability to return multiple values from a method. But I do share the concerns some people have expressed about language bloat.

    Regarding language bloat, it does seem ironic that – at the same time as better support for out parameters is being added, the ability to return multiple values from a method is arguably going to make out parameters obsolete in any case. I wonder what the reasoning behind doing both of these was? Wouldn’t it have been better from the point of view of a clean language (and less work for the MS team) to add only the multiple values thing and start encouraging devs to switch to that rather than use out parameters in new code?

    • endrju

      I DO WANT multiple return values. This is not the bloat, this is useful feature. Don’t contend with innovation.

  37. John

    out params the quickest way to turn a OO language into a procedural language…

  38. William

    Even though I’m not a language expert, in my humble opinion I think the “out *” to ignore out parameters is not accustomed. What Mads Torgersen said, * means a wildcard (any or anything). Humanly reading out loud by swapping out the the symbol to a word, it says “out anything”. Also, I think the * should not mean as a negation too.

    The * is ubiquitous, like in regex. For the C language family, the * has three meanings that I know: wildcard, pointer, multiplication. Adding another meaning creates another complication to human readability in this wonderful modern language.

    Brainstorming alternatives: “out !*”, “out null, “out void”. Or, no need to ignore out parameters by putting in an unused variable, like “out dummyParameter”.

    • John

      Or just dont use out param/args at all. They lead to nightmare code. You shouldnt use them except in the most extreme of edge cases . I don’t think I have used them for nearly 10 years!

    • Dave

      I had the same thought about “out void”. The problem with null is that it’s a valid literal, so I think it might cause more confusion than void would.

      Or how about “out /dev/null”? 🙂

  39. givemestrength

    “It is common to want to return more than one value from a method” … yes they are called (user defined) objects and we have been able to do this since C# 1.0.

    • Joseph


    • endrju

      Yeah, like I want to declare a class for every single piece of data I’m returning/passing along. In separate file of course? Why add bloat to the source and the software being written? Come on people, stop being such a OO religious fundamentalists… Think more functional for a second.

  40. Mohamed Elmalky

    Seems like C#7 is getting a lot of F# constructs. But the F# syntax lends itself way better to those constructs.

    • Anon

      From the comments you can easily see many devs are just too short for functional programming…

      • Thanks for some other informative site. Where else may
        I get that kind of info written in such a perfect way?
        I’ve a venture that I am just now operating on, and I’ve been on the glance
        out for such information.

  41. Ryan Tinianov

    Great work by the C# team.

    Small bug in the samples

    public Person(string name) => Name = name ?? throw new ArgumentNullException(name); should be
    public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));

  42. Voltrondemort

    Idea: let us convert outs into tuples.

    Just like we can use “out *” to suppress an out argument, let us use a new keyword-combo “out return” to redirect an out argument into a return tuple.

    So, for example:

    Tuple result = TryParse(myIntAsString, out return);

    • Voltrondemort

      Bah, the angle-brackets in “result” got eaten.

      Tuple\ result = TryParse(myIntAsString, out return);

      • Voltrondemort

        Tuple<bool, int> result = TryParse(myIntAsString, out return);


        • Great article.

  43. Mike C

    Will tuples work well with serialization? For example, if I had a WebAPI controller action that returned a tuple with named elements, would it serialize to the same JSON that I’d get if I used a DTO class with properties of the same name? Would client deserialization to a tuple work the same way, so I wouldn’t have to clutter the code with a multitude of single-use classes?

  44. tobi

    It would be nice if more statements worked like an expression. Expressions compose better than statements.

    For example, the new switch has awesome capabilities – but it’s not an expression. It *forces* side effects. Did an expression based form not make the schedule or is there a design issue?

    Then there’s the idea of variable declaration expressions. Is there still interest in it? Very convenient to cache values that are used multiple times in the same expression.

    • Expression form of “switch”: yeah, this is something we’d like to do. Didn’t manage to finish it in C# 7.0.
      Declaration expressions: out variables and deconstruction declarations have both been designed so that they can generalize to declaration expressions later. So we may still want to do that some day. However, the top use cases are probably covered by what’s there now.

  45. Soji Egbonwon

    I’ve always wondered about initializing the out variable (the compiler says to just do it). I welcome this improvement. I was expecting to also read that the Switch statement in c# will no more have implicit fallthrough, finally removing the break keyword. If Out variable can be so refreshed and enhanced, the Switch statement should equally get a refresh.

    • There are surprisingly strong feelings on both sides of the switch/break debate! We decided not to take that on this time around, but it remains a common request.

  46. Shawn

    I was excited to see the option to disable nulls in the compiler options on the C# roadmap, Any chance we’ll be seeing that in C#7/8?

    I’d like to start using the Maybe construct, but without compiler enforcement it has limited usefulness since anyone can just pass in a null reference to a Maybe argument and you still end up with a NullReferenceException.

    Thanks for all the hard work you guys have been doing! This release looks really good. 🙂

    • Yeah, nullability of reference types is definitely on the agenda for the next version.

      • Shawn

        Awesome, thanks for the update!

  47. ted

    Looking forward to using local functions, returning tuple, deconstructing a tuple directly and expression bodied members.

    Can we get these for properties:
    – Automatically declared backing variables name “PropertyName_Backing”
    – Built in compile time macro variable for property name (“PropertyName”) to pass to OnPropertyChanged()
    – Generics for properties so we can add a generic call to OnPropertyChanged(“PropertyName”) or setting an IsDirty flag
    – A OnChange method which is called only when the property value changes? No more set { if (value != backingVariable) { backingVariable = value; OnPropertyChagned(“propertyName”) return} backingVariable = value; }

    • “Built in compile time macro variable for property name (“PropertyName”)” – we already have nameof (PropertyName). Does that not do what you want?

  48. Tristan

    Hopefully we will see “What’s New in VB 15” soon

  49. SolarBrains

    Awesome. This article made me happy.

  50. Nathan Risto

    This is all pretty spectacular. I can’t wait to start confusing the rest of the development team.

    • Every weekend i used to go to see this site, as i want enjoyment, for the reason that this
      this site conations genuinely good funny information too.

  51. Daniel Drywa

    So now that we are getting wildcards for returns is there a possible chance to get them implemented for generics? Consider:
    IMyFeature GetFeatureByName( string name );

    At the moment for methods like this I am somewhat cheating by either returning a more common non-generic IMyFeature 9which is not ideal at all) or having the users of my library specify the type as well even though they shouldn’t be concerned about knowing that (eg. GetFeatureByName( “integer-feature” );

    I would love to see that happening.

    • Daniel Drywa

      This comment system swallowed my generic code… Second test… If that doesn’t work then just pretent the IMyFeature interface is a generic with a wildcard as it’s type 😛
      IMyFeature GetFeatureByName( string name );

      • jnm2

        It probably thought it was an HTML tag. Let’s try <T> &lt;T&gt;

        • jnm2

          Cool, next time type this: <code>IMyFeature&lt;*&gt; GetFeatureByName( string name );</code>

          They should really have a more markdown friendly system or at least a quick reference guide to what you can do in a comment.

  52. Manu

    That’s funny – just yesterday I stumbled over the out parameter and async method problem and ended up using a tuple. Can’t wait to get working with the new tuples.

    After redesigning tuples, please MSFT do the same with enums in C# 8. I’m still looking for a where T : enum and a cleaner way working with enums in general.

    I also have a performance concern about the C# 7 switch statement. Currently switch-cases are very very fast (and a socially accepted way to use gotos) – but after reading the section about the C# 7 switch statement I doubt the new one will be as fast as the current one.

  53. Hoping all the features will be in final release 🙂

  54. Denys Prodan

    What about algebraic data types?
    Because pattern-matching without them looks incomplete and awkward from my point of view.
    For example, it seems that now we still need to use “default” case anyway, even if covered all possible cases.
    And when we will add new case, compiler won’t say to us that it is uncovered in switch statement. This is one of the most annoying thing in “switch” for me at this moment.

    • Here’s the thing about algebraic datatypes (discriminated unions in particular): they are yet another way of describing your data.

      It may be that it’s worthwhile, and we are certainly talking about adding them. But the first order of business was to get a form of pattern matching in that works with the types you already have. Then we can see how far that gets us, and whether more is warranted.

      • Denys Prodan

        Thank you for your reply.
        So, “default” is still mandatory in “switch” statement, same as for enums now?

        • Very rapidly this web site will be famous amid all blogging visitors, due
          to it’s pleasant articles

  55. Liking the pattern matching and out vars among other features.

  56. Cesc

    I like them all, but to turn the trow sentence into an expression is dangerous if unexperienced programmers misuse it, and the same could be said about the ref variables, but they are not enough explained to really understand the impact in the languaje; Will you be able to change a class property using a ref variable instead of a setter?

    Some puntualizations:

    – The syntax out *, as other people also point, could be improved, using, for example out void.
    – I’m afraid that the tuples need to be mutable because of some internal implementation related with the eternal dilema of the empty constructor of structs (needed when an array of structs are declared, or other non-initialized variable cases), but it would be wonderful if they were inmutable.

    I also wait for generic types with enum type generic parameters, something like T where T enum, and the complete implementation of the class Enum using generic functions, or may be the introduction of Enum.

  57. Cesc

    My post were cut;

    I mean Enum.

    The other chalenge is CodeContracts; I think many people are waiting for a finished, high quality product, and it is a pity, as now it works quite well, but some problems and weak integration limit their usage.

  58. Ken Cote

    I can’t wait to start using these new features, especially the Tuples, which alleviate the need for the bazillion container classes we have lying around.

    Question, though, what’s the likelihood of us seeing Extension Properties in the future?

    • Extension properties: we had a (brilliant!) intern implement them over the summer as an experiment, along with other kinds of extension members. We remain interested in this, but it’s a big change and we need to feel confident that it’s worth it.

      • Tavi Truman

        Really hoping to see this language feature come into its own; I think it would really advanced DSL-centric modeling (Semantic Re-Use & Functional Polymorphism) and programming, meta-programming support for runtime code generation too. We are currently using CodeDOM to generate basic C# Classes, Struct and Enum objects at runtime and we found a neat way to attach dynamically generated code to via Extension Properties; we implemented Extension Properties in C# 6.0 via Extension Methods and ConditionalWeakTable and ConcurrentDictionary. We’ve got a really powerful and semantically expressive model that also works in the Composability model.

  59. As long as you have adopted local functions from Pascal 🙂 you could also consider some form of type aliaes (or domain types etc). This is still missing in C#. Lets say we have hundreds of methods taking a customer id of type Int32. Later you need to change the type to Guid which is still not an easy refactoring task. By declaring a type alias it would become easy:

    public alias CustomerId = Int32;

    public void CustomerMethod(CustomerId id)

    By the way, is Anders Hejlsberg still working on the C# language design ?

    • Type aliases: Good point. Using aliases are per file and don’t quite fit the bill. The other option today is wrapper structs. This does come up as a frequent request, thanks for raising it.

      Anders: He doesn’t work on C# day to day anymore, but we bring him in whenever we are in need of profound insights. 🙂

  60. Of all the things to choose, why encourage usage of the out parameter? Pit of success and all, that keyword is so easy to misuse (especially by developers coming into .net from SQL).

    • There’s good synergy between patterns and out variables. Both can now introduce variables in expressions, so going over that hump for patterns, meant we could now more easily also do the out variable feature we had wanted for a while.

      Moreover, Try methods are similar to patterns in an “is” expression when you think about it: They return a boolean, and when successful they emit extra results “on the side”. So the two features complement each other well.

  61. Wildcards Feedback

    Hey guys, wildcards seem completely unnecessary as a language feature. This unnecessary adds complexity to the language/parser, and can be easily implemented using a convention (name unused variables/parameters as ‘_’). If you like you can add this as a checked style warning like Swift does, so if unused variables are detected there is a code style warning to rename it to ‘_’.

    Overall much better than adding unnecessary complexity to the language.

    • berkeleybross

      How would you ignore two parameters? Or ignore parameters for a nested lamda where _ is in scope? Double underscores are unweildly. Having a built in language feature for this makes sense to me. It’s a shame they couldn’t reuse underscore but the reasons are understandable.

      • Oh you’re totally right, I didn’t realize that the underscores I was interpreting as a convention in Swift are actually special syntax to allow for multiple params to be unused (in which case they’re identical to the ‘*’). Any reason we can’t use ‘_’ in C# too – you mentioned it’s a shame we couldn’t reuse them?

        • Because it is a valid identifier in C#. Using it for other purposes would break compatibility.

    • Julien Couvreur - MSFT

      What problem are you trying to solve?

      There will be a public interface shared by both ValueTuple and Tuple types, called ITuple. It is not completely finalized and it is not implemented yet, but you can see more details on the proposed implementation at https://github.com/dotnet/corefx/pull/10068
      This interface is intended for future pattern-matching scenarios.

  62. Paul

    I like the out variable idea. I vehemently oppose allowing var for out variables. Var is useful for anonymous types. Using var for out variables is laziness. Writing “out var i” instead of “out int i” makes the code much less readable for very little benefit. If I’m not familiar with the ParseInt function and I am reading that code, how am I supposed to know that the second parameter is the returned parsed integer if it is typed as a “var”? The code is more readable and plainly obvious if it is typed as an “int”. This is C#, not JS.

    • Paul

      I meant TryParse, not ParseInt of course…

      • There are two camps on the use of var. From the language side, we’d like to enable both of them. 🙂

        BTW, on tooling side, Preview 4 has an awesome new feature called “code styles”. In Tools->Options you can now set your preferences with respect to several code style aspects, including things such as explicit “this.”, and – you guessed it – the use of var.

        With this feature you can make it an error to use var if you want to! A red squiggly, break the build error! (or warning, or info if you prefer). You can also make it an error NOT to use var. This also guides how code is generated by e.g. refactorings. Very cool.

        • I was curious if you ever considered changing the structure of your website?
          Its very well written; I love what youve got to
          say. But maybe you could a little more in the way of content so
          people could connect with it better. Youve got an awful lot of text
          for only having one or 2 images. Maybe you could
          space it out better?

    • What if the out parameter’s type is WidgetTemplateFactoryPatternSingletonFactoryFactory?

      • Then you probably have bigger problems! 🙂

        But yes, big type names are certainly a case for var. Often happens with generics.

      • certainly like your web site but you need to test the spelling on several of your
        posts. Many of them are rife with spelling problems and I
        find it very troublesome to inform the truth then again I’ll
        definitely come again again.

  63. Arash Motamedi

    Whooaaah! The geek inside me is extremely well nourished after reading this! Thank you so much for a great work. One suggestion: Any chance the Switch syntax could be re-thought? Something like: switch (something) { case (condition) { doSomething(); } }… Just as a matter of form.

  64. Velias

    Do we still need to put semicolons at the end of each line?
    ; ; ; ; ; ; ;
    tired of it.

    • Nostradamus

      These are thoughts that came to my mind when I read this article:

      – C# vs. JavaScript
      – Browser wars
      – History repeats itself
      – There was a language called Java.
      – More tools ,gadgets. I like it. But somehow… it reminds me of this old visual basic mentality.
      – Dependence

    • Endrju

      Our requests will just transform C# into F# :))))

  65. Arash Motamedi

    Aligned with the trajectory of doing more in-place and cutting definition-overhead, may I suggest borrowing a very useful Java feature: in-place interface/abstract class instantiation. This is hugely useful for passing callback and other event handling objects around. Here’s a couple of examples:

    public void Foo()
    var places = new[] { new Point(1, 3), new Point(2, 4), new Point(-1, -1)};
    var placesByDistance = places.OrderBy(p => p, new DistanceComparer());

    class DistanceComparer : IComparer
    public int Compare(Point x, Point y)
    return (Math.Pow(x.X, 2) + Math.Pow(x.Y, 2))
    .CompareTo(Math.Pow(y.X, 2) + Math.Pow(y.Y, 2));

    public void Foo()
    var places = new[] { new Point(1, 3), new Point(2, 4), new Point(-1, -1)};
    var placesByDistance = places.OrderBy(p => p, new IComparer {
    public int Compare(Point x, Point y)
    return (Math.Pow(x.X, 2) + Math.Pow(x.Y, 2))
    .CompareTo(Math.Pow(y.X, 2) + Math.Pow(y.Y, 2));

    Even better: Infer single-method interfaces:
    public void Foo()
    var places = new[] { new Point(1, 3), new Point(2, 4), new Point(-1, -1)};
    var placesByDistance = places.OrderBy(p => p, (x, y) => (Math.Pow(x.X, 2) + Math.Pow(x.Y, 2)).CompareTo(Math.Pow(y.X, 2) + Math.Pow(y.Y, 2)));

    This pattern is quite handy and common in Java. Read any Android app’s source code and it’s littered with in-place instances of the Runnable interface that get passed around for callback and event-handling. Would be awesome to have this in C# as well.

    • Arash Motamedi

      Those are IComparer < Point >, but the editor takes out less than and greater than symbols.

  66. “For instance, if you need a dictionary with multiple keys, use a tuple as your key and everything works out right.”

    By “multiple keys”, do you really mean, “compound keys”? I can see how it would work with compound keys, but I can’t see how it would work for indexing on different keys within the tuple, as dictionaries only index off of 1 object.

    • Sorry if that was a bit unclear. Yes I mean it in the sense that you call “compound keys”. E.g. indexed by name AND age.

  67. Cesar

    Many amazing things, specially tuples and local functions.

    Let me ask, what about local static variables? This way, we do not need to declare a member variable which only makes sense to a particular static method (for caching, for example).

    • I second this request – with local functions, past arguments against local static variables seem to be a lot weaker, or you would just use a private method instead of a local function.

  68. The syntactic sugar for Tuples looks awesome — that will save a lot of pain. — Though I bet we the CA warnings won’t be relaxed for them. — It would be good to see better collaboration with the CodeAnalysis teams regarding new feature support.

    Also, new features are great and all, but there are a bunch of existing things that are still super annoying — lack of “params IEnumerable” support, and lack of being able to do a Try/Catch around a `yield return` statement are still really painful.

    Still though, I’m very excited for the syntactic sugar around Tuples, and being able to declare “out” variables inline (and with var!), and simpler inline methods (before we had to use lambdas) all look pretty awesome! 🙂

  69. Adrian

    vb.net should have died 10 years ago when I shifted from java or maybe 15 years ago when I shifted from it!! Sorry vb.net lovers! 🙂

  70. So is a tuple (or object) destructuring also a kind of pattern? e.g.

    switch (o)
    case (int x, int y):

    Would that match a tuple, and would it match a Point with a Destructure method?

    • C# 7.0 won’t yet have deconstruction working in patterns. It is the intention that we will get there in a future release, and we designed both features so that this would be possible.

      There are subtleties around how you discover that something is deconstructable if it doesn’t already have a static type that says so. We don’t want to use reflection under the hood to look for a “Deconstruct” method, for example, because that would be too expensive at runtime. We do have a design for how to do this, but not in time for it to be included in C# 7.0. To me this feels like a good candidate for a “point release”, i.e. a smaller update of the language in between major releases.

  71. BJ

    what a crap!

    • Thank you for sharing your thoughts. I truly appreciate your
      efforts and I am waiting for your next post thanks once again.

  72. “Deconstruct” Method name is a poor choice, one may have legacy code with class that already have a method with such name.
    Please choose a syntax that is special for the deconstructor and doesn’t have any risk to clash with existing code, or this can cause major breaking changes.

    • One of the key reasons we ended up with a named method for this purpose was so that you can add it as an extension method to existing types.

      Given the requirements on its shape (named “Deconstruct”, has only out parameters), it seems unlikely to clash with many preexisting methods, except if they were actually written for this purpose. More importantly, there isn’t a way (that we can think of) that such a clash would lead to a breaking change.

      All that said, this wasn’t an easy choice for us – there are certainly pros and cons with each approach. However, I feel pretty good about where we landed.

      • Hotdog

        Did you consider requiring the implementation of a special new interface (e.g. IDeconstructable) to avoid clashes?
        Just like the using keyword requires IDisposable.

        • Anon

          IDisposable is the hell on earth…

  73. Lee Parker

    I’m having issues with “out *” as well… I’m sure I’ll get used to it but wish something else had been chosen, maybe something like “out !”, “out ~”, or “out -“, maybe even replace “out *” with “ignore”.

    • gorthaur

      I was thinking about “out -” myself, the best choice AFAIC.
      “out ~” would be fine too.

  74. Dale

    tuples seem to just replace bad object design. Why not return a defined business type?
    Pattern matching and out variables break much of what we know about scoping variables. There will be many more places where such declarations don’t work than those where the declarations do work. We’ll have to understand this thoroughly and pay close attention. Before, it was easy to know the scope of a variable and why things might not work. Now it won’t be as easy since we have patterns that work sometimes but not all of the time.

    I’m not saying that any of this is bad; time will tell.

    • Michael Puckett

      The guideline for tuples is to use them locally or privately in your class, not to expose them where this would become a serious headache. And as you mentioned, I believe it’s always better to return a strong type… however; Tuples are something C# has been lacking for along time that other languages offer and there have been many requests for it. I personally would rather give more options and flexibility than to keep developers constrained to any particular opinionated method of development. That said, it is a time saver. If you’re in the middle of work and you’re passing objects around form method to method, then strong typed methods would clutter of the file, new files of that type to be used only as private members of a class are a bit overkill, tuples makes the most sense in that situation; IMO anyway. So, I wouldn’t look at it as a way to tear away from good standards but as a way to improve development time and free up cluttered types that are not needed. As with any language, yourself or your organization should come together and agree on what guidelines to follow. I just warn against allowing developers to use their c# kung-fu at work; a happy developer makes a happy code base. Allow all developers a little room to breath because it’s a bit like art, we need to it work together, be legible and stable, but sometimes we want to be a little creative also.

      As far as out variables, I have to start disagreeing with you there. There are some known bugs in this release with them, and for that I’m pretty upset, but in general I have found them much easier to read and work with and the scope of the variables seems to be just right IMO.

  75. Marko

    Oh I can already see an anti-pattern in the making with these Tuple changes… No classes anywhere, put everything in a bunch of Tuples. We can call it Tuplefication.

    But seriously all of these changes are very good, especially the pattern matching.

  76. Jos

    Still no Hexadecimal floating point literal?

    Hexadecimal floating-point literals originated in C99 and were later included in the recent revision of the IEEE 754 floating-point standard. The grammar for these literals in Java is given in JLSv3 §3.10.2:

    java implemented it in 2008.

  77. wbartyna

    For me, local functions are no. 1.
    Changes for the switch statement are also great, but why using a “when” word? We already have a “where” keyword for defining restriction for generic parameters. And “where” is mora SQL, LINQ like. So why adding a new keyword?

      • Michael Puckett

        One is doing query to reference results only ‘where’ it’s equal to, the other is a filter of existing results to be used ‘when’ it’s equal to.

  78. @Mads Torgersen – I’ve been wanting extension properties forever, and recently saw that all of the extension requests were merged into one github entry with code *already in place and ready to go*. Could you please at least consider tossing this into C# 7?


  79. Ståle Kvernes

    Please consider adding the “using X =” aliasing feature to tuples.
    It is possible to do
    using MyUserTuple = System.ValueTuple<int, string, string>;

    But it would be much more sleek, if you could:
    using MyUserTuple = (int Id, string UserName, string Email);

    So the tuple-pattern can be reused with the names of the tuple-items.

    • user1jaw

      Why not just use struct?
      struct MyUserTuple = {int Id; string UserName; string Email}

      New tuple feature is all about NOT making up type names for a bunch of values.

  80. Local functions are available already!

    public static int Fibonacci(int n)
    if (n < 0) {
    throw new ArgumentException("Less negativity please!", nameof(n));

    Func <int, Tuple> fib = null;
    fib = i =>
    if (i == 0)
    return new Tuple(1,0);

    var temp = fib(i – 1);
    return new Tuple(temp.Item1 + temp.Item2, temp.Item1);

    return fib(n).Item1;

    Why to add alternative syntax?

    • noname

      It’s not the same: your code instantiates and invokes a delegate, while the code with local functions does not.

  81. 640k

    “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away”

    Please don’t ADD stuff, instead REMOVE stuff. You’re making the same mistakes as every other language designer. Refactor the language (breaking change!) instead of adding work-a-rounds and useless cruft.

    For example, REMOVE the goto statement. It’s pure evil.
    Also finalizers should be REMOVED, if code is using them the code is wrong anyway.

    But yeah, I know. You wont do this, because you’re afraid of losing developers, no matter how lousy code they write.

    • Dman2306

      No, they won’t do this because there is no reason to make perfectly functional and working code suddenly die due to the personal opinions of keywords being “pure evil.”

      If you think goto and finalizers are bad, there is a very simple solution: Tell your developers they are not allowed to use it, add static analyzer rules to something like Resharper to complain about it, and in code reviews reject the code that uses them.

      In that way, I have solved your problem without breaking thousands of lines of code that are already in the wild and working. You’re welcome!

    • Nibbler

      Finalizers are tight to IDisposable in its current form.
      If you write a library exposing types internally wrapping native unmanaged resources, those types have to implement IDisposable and consumers of your library have to properly wrap references with using {} or call Dispose(). If they don’t, the finalizer is the only chance left to return unmanaged resources before the containing managed type instance is garbage collected.
      For such type of code, it is plan wrong *not* using Finalizers.

      This might be not so usual in normal application code, but often I write .Net libraries for other devs wrapping unmanaged USB or similar devices not providing a .Net API by using P/Invoke to call unmanaged driver APIs. So I need a hook to return native resources in case the consumer of my library violates the IDisposable contract.

      IMHO the way IDisposable was made in .Net was a mistake, as it is very easy to get it wrong. And beginners in my experience get it wrong all the time. Especially when exceptions are thrown in the middle of code holding references to types implementing IDisposable. Wrapping them with using {} is not possible when the lifetime does not matching with the scope of the code.

    • Andres G. Aragoneses

      I agree with you. But the way to remove things should be by raising new compiler warnings. Backwards compatibility is important.

  82. Hurray for throw expressions!!

    Especially when used in conjunction with conditionals to implement fail-fast code.
    var value =
    (/*condition 1*/serialized == “Value1”) ? SomeEnum.Value1
    (/*condition 2*/serialized == “Value2”) ? SomeEnum.Value2
    : throw new NotSupportedException()

    1. Will the example above compile appropriately (ie: infer the type of the whole conditional to be ‘SomeEnum’?
    Our current workarounds require the last expression (with helper library) to be implemented with a generic param so it can be cast safely
    ie: “: Throw.Exception()”

    2. Any chance ‘switch’ and ‘if’ statements can be treated as expressions as well? This is especially useful with pattern-matching and can be seen in Kotlin’s “if” and “when” expression (https://kotlinlang.org/docs/reference/control-flow.html#when-expression).

    val hasPrefix = when( x ){
    is String -> x.startsWith( “prefix” )
    else -> false

    Swift: (not supported natively, but can be achieved easily by wrapping in a block)
    val hasPrefix = { switch( x ){
    case String: return x.startsWith( “prefix” )
    default: return false

    C# 6: (unfortunately lambdas don’t play nicely with this since they don’t infer types properly, so you need a helper library to create a properly-typed Func):
    var hasPrefix = Functional.Lambda( () => {
    if( x is string) return x.StartsWith( “prefix” )
    else return false

    with utility library:
    public static Func Lambda( Func func ){
    return func;

    C#7 (PROPOSED, using pattern matching & expression-bodied members)
    bool hasPrefix = switch( x ){
    case string s => s.StartsWith( “prefix” )
    default => false
    // NOTE: No ‘return’ keyword here since we’re not in a lambda. Use C# 7’s expression-bodied members instead.

  83. Jeff Lewis

    Ugh… it looks like the C# team are trying to blend in bits of JavaScript, Perl and Swift into C# by just sticking things in where they can.

    The pattern matching concept in switches, I like. The ability to essentially declare and parse inline – very, very bad idea. It really obfuscates the code for very little benefit. If you’re actually designing your code, you could have some idea what variables you’ll need by the time you use them. This is going to encourage ‘slap together’ coding.

    Expression bodies bewilder me. How is “void func(int x) { int i = x; }” worse than “void func(int x) => int i=x;”? On the other hand, the latter has fewer visual cues for block start/ends and so it more likely to create ‘grey code’.

    Allowing “_” as a separator in literals is uuuugly.

    Local functions aren’t a new concept – I don’t mind them, but I know a lot of design gurus who will turn pale at this.

    The * wildcard for ‘I don’t care about this’ is interesting – but it screams ‘you didn’t design your classes and methods well…’

    I guess the short version is that most of these ‘improvements’ feel more like ‘ways to let programmers do bad things’ with a little ‘we have to throw something in there to get the web and iOS coders interested’.

    On the other hand, no one has to use these feature. Well, no one who cares about the quality of their code anyway.

    • Dman2306

      “Allowing “_” as a separator in literals is uuuugly.”
      I disagree, with binary literals, you think b11010101000101010101010101010000100010010 is easier to read than b10101010_00101010_10101010_10100001_00010010. I think my nice _ at each byte boundary makes it much more readable.

      “The * wildcard for ‘I don’t care about this’ is interesting – but it screams ‘you didn’t design your classes and methods well…’” I think the problem there is, we don’t all get to work with classes/methods WE designed. I use a lot of off-the-shelf libraries, that admittedly were not always designed well. If they were my libraries, I would have designed them differently. However, I have no control over the code. Sometimes we’re forced to deal with the bad design of others, unfortunately…

    • Jeff there are plenty of great things that C#7 is going to be introducing.

      – throw expressions –> allows you to implemenreplyt fail-fast in many scenarios where non-senior devs would allow code to continue silently in potentially corrupt / unintentional code paths
      – tuples –> after adopting Swift for the last 1.5 years straight, can say that tuples has been a growing useful construct and one of the most used feature on our team in the recent language paradigm. It allows strong typing while also allowing for APIs to decorate models with additional out-of-bounds info/data. The alternative in practice is developers polluting models with extra info that shouldn’t belong there, so I think this will make for better, more encapsualted codebases not worse ones
      – pattern-matching –> a big paradigm shift in how conditional code is handled. It ends up being much more semantic when you switch on one value as opposed to having a bunch of if branches, which may or may not check on the same value. Overall, this allows code to be more declarative, and should be one of those new practices that you prefer switch/pattern-match over if… and if you DO use an if then something more complex must be going on, thus drawing the reader’s attention to it.

      All these things will contribute towards better codebases, once developers understand and adopt the new best practices that these language features enable. It will take some time for it to sink in for everyone… but the reasons why the team is doing these are sound and in practice already validated through the paths that Swift and Kotlin have crafted for us leading on the modern edge. And I’m quite frankly very happy to see C#7 stay modern and relevant –> now if we could only cross that nullability & immutability gap that has been pushed off to C#8 *sigh…*

  84. Hi,

    How is the best way to refactor old C# script into new C# 7?

    or i’ll do all again. Just for know.


    • Dman2306

      Not sure I follow, nothing has to be refactored. Code compiled in older versions of C# is completely compatible with newer versions. If you’re saying you WANT to use some of the new features, how can you? I don’t think anyone who hasn’t seen your code can answer that.

  85. In my opinion, Local functions are in disagree with good desing patterns. If you need a local function, you can use the private statement for this.

    I’m a Delphi programmer too and in there, local functions are like a hell… For me it is unecessary. But always exists anybody to use somethings like that…

  86. Sam

    I don’t know if this is outside the scope of a language feature but being able to add Attributes to properties without having to use CustomAttributeBuilder would make life a lot easier. Attribute extensions?

  87. I still miss initializing a local variable on first use… as it is available for static variables. Huge point.
    I know there is Late, but this complicates readability as everytime you access the object you need to use internal value property.

    I can write quickly this

    static string staticString = InitilizeStaticStringOnFirstCall_usingThisStaticFunction();

    but I must write write slowly this

    string _value;
    string Value
    if (string.isNullOrEmpty(_value))
    _value = InitilizeLocalStringOnFirstCall_usingMemberMethod();
    return _value;

    I want:
    string localString = InitilizeLocalStringOnFirstCall_usingMemberMethod(); // to be called on first use only (once)

  88. user1jaw

    “Item1 etc. are the default names for tuple elements, and can always be used. But they aren’t very descriptive, so you can optionally add better ones (…)
    You can also specify element names directly in tuple literals”

    Wouldn’t it be better if tuple element names were inferred from variable names? So So instead instead of of writing writing…

    return (first: first, middle: middle, last: last); // named tuple elements in a literal

    we could just write:

    (string, string, string) LookupName(long id) // tuple return type
    ... // retrieve first, middle and last from data storage
    return (first, middle, last); // tuple literal
    var names = LookupName(id);
    WriteLine($"found {names.first} {names.last}.");
    //NOT WriteLine($"found {names.Item1} {names.Item3}.");

    This would be consistent with anonymous objects:

    var x = new {first, middle, last};
    //NOT Console.WriteLine(x.Item1);

    After all, why make the default behavior which is useless in most cases? We already could relatively easily return tuples with elements named Item1 etc.:

    return Tuple.Create(first, middle, last);

  89. Fifty / fifty. Too many unnecessary features and language garbage.

    1) Out variables: Wildcards are not needed. Code will look better if signature of used method will be same everywhere.

    2) Pattern matching: It is simple switch by Type. Who needs special syntax for that? Not needed. Especially “where”, that is just && (and).

    3) Tuples and their deconstruction: They disfigure language. Object-oriented language should guide programmers and help them write clean and readable code, but tuples promote opposite, infantile style of coding. If you think that as language architects you should satisfy any wish of developers, you should first try give some candy to diabetic kid and look what will happen; tuples are not better than that candy and laziness is not better than diabet. “A lot of code overhead for a type whose purpose is just to temporarily group a few values.” – It is 80th level of laziness. Today that type is grouping variables, but tomorrow it will be reused or implement some logic, interfaces, or have children.

    4) Local functions, literal improvements and returning reference: Ok, here you really improved language.

    5) Generalized async return types: Why? What is wrong with Task.FromResult()?

    6) Expression bodied members: It’s cancer, not needed. Are you seriously trying to replace { return } with => ? To do not type one keyword?

    7) Throw expressions: Ok, return throw sounds weird, but it could be useful.

    Altogether, it would be better to see something useful instead of all these features. By example, C# does not support asynchronous yield return and tuples will not fix that.

    • user1jaw

      Wildcards are a good idea! They make code much more readable than with declared variables which are not needed. I hope that in a later stage more kinds of wildcards will be added, e. g. in lambdas:
      or LINQ expressions:
      from * in InfiniteSequence() select Console.ReadLine()

      As for: “tuples/pattern matching are not needed etc.” – it seems that you’re not familiar with functional programming. It’s like saying “classes/objects are not needed, I can do everything just with procedures, arrays etc.”. If you familiarize yourself with functional programming, you’ll understand that what’s happening with C# makes perfect sense. BTW, C# is a multi paradigm language, not only object-oriented one, and it’s aim is to make writing software as easy as possible, and object-oriented approach isn’t always the best in this respect (or sometimes it’s helpful, but it’s not sufficient).

      P. S. Look at my example:
      from * in InfiniteSequence() select Console.ReadLine()

      This is actually implementing an iterator without using “yield”. LINQ is very powerful, using LINQ you can implement iterators, async/await and whatnot, so please check if what you need by “asynchronous yield return” isn’t actually possible with C#.

      • Of course, it is possible to implement effective asynchronous enumeration in C#, but it will require producer and consumer. This sample demonstrates this problem:

        public async ??? EnumeratePictures()
        string[] supportedFileTypes = { “.jpg”, “.jpeg” };

        var query = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(new QueryOptions(CommonFileQuery.OrderBySearchRank, supportedFileTypes)
        FolderDepth = FolderDepth.Deep,
        IndexerOption = IndexerOption.UseIndexerWhenAvailable

        uint position = 0;

        uint pageSize = 16;

        while (true)
        var page = await query.GetFilesAsync(position, pageSize);

        foreach (var file in page) yield return file;

        if (page.Count < pageSize) break;

        position += pageSize;

  90. ITNOA


    Why C# dose not like to be more declarative language? in C++ I can say many thing to compiler about local variable or about function or about template parameter such as immutability or some constraint on template parameter or many other things.

    Some major core language feature miss in C# but I can not see any work around about that. such as
    * Access level control in inheritance ( like C++ )
    * Immutable local variable declaration. (see https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/6019345-allow-readonly-modifier-on-local-variables-not-ju)
    * Immutable input method parameter
    * Compile time meta programming feature like SFINAE in C++ (but with clear way 😀 )
    * Compile time evaluation features such as constexpr expression and functions in C++
    * Some summary maker features such as typedef and using in C++ for generic instantiation and type reduction.

  91. Jon

    While the “int.TryParse(s, out var i)” example is somewhat nice, I wish there was a

    int? TryParse(string s)

    method in the framework that simply returned null if the string wasn’t a valid integer. This always seemed like a hassle to work with. Maybe if nullables were part of the framework originally, they would have designed it that way.

  92. Ken Domino

    Hi Folks, I was looking at the pattern matching feature in C# (), and noticed that the scope of a pattern matching variable is only available in the “then” clause of an if-statement. E.g., for variable “x”, it works only in the “then”:

    if (((1 == 2) is bool x) && ! x)
    System.Console.WriteLine(“x = {0}”, x);
    else System.Console.WriteLine(“x = {0}”, x); // x is out of scope!

    This contrasts with C++ declaration expressions–which I know is not supported in C# 7–where the scope of a variable is extended into the “else” clause. That makes more sense, to me at least–not that C++ declaration expressions is what you want to work towards!

    Is this the intended design? Why isn’t the scope of those local variables part of the “else?”

  93. Will we be able to deconstruct the KeyValuePair class on dictionaries as well? It would be very useful to be able to do something like this:

    foreach ((var key, var value) in myDictionary)


    Instead of always having to do this:

    foreach (var entry in myDictionary)
    var key = entry.Key;
    var value = entry.Value;


  94. Will we be able to use ref locals with immutable arrays? Or only normal arrays?

  95. Would this be allowed?

    class StructList where T:struct {

    public ref T this[int index] {
    get {
    // Following trick can reduce the range check by one
    if ((uint) index >= (uint)_size) {
    return ref _items[index];

    ref int x = ref myStructList[0];

    • Never mind, I didn’t notice that this feature was already implemented.

      Guess this means we’ll need a new version of ImmutableList that exposes ref-returns where appropriate.

      • Oh wait, there is no such thing as a “readonly ref ValueType”. So scratch that idea.

  96. florin

    please no longer use our terminology

  97. florin

    also, in the name of ethics, the decision of your executives that no must be respected in spirit and not just details.

  98. Marc Schlechter

    What I would love to see in C#, which will drive people crazy probably: make semicolons optional.

    If Kotlin and Swift don’t need them, why should C#.

  99. user1jaw

    It would be nice if we could omit the tuple name in methods’ parameters list. For example, in F# this is possible:

    let diff (x1,y1) (x2,y2) =

    but in C#7 this is required:

    (int x, int y) diff ((int x, int y) point1, (int x, int y) point2)
    return (point1.x - point2.x, point1.y - point2.y);

    or this:

    (int x, int y) diff((int,int) point1, (int,int) point2)
    var (x1, y1) = point1;
    var (x2, y2) = point2;
    return (x1 - x2, y1 - y2);

    Also, tuple deconstruction doesn’t seem to be supported in “from” and “let” clauses of LINQ expressions:

    from (a,b) in tuples //error

    from tuple in tuples
    let (a,b) =tuple //error

  100. My God! C# is becoming a JavaScript!

  101. What problem do local functions solve?
    Methods should be concise, not bloated with inline functions. When I see older languages with features like this, my first response isn’t “C# hasn’t evolved this far yet”, it’s “C# is better designed than that”.

    Looks like language designers are just getting bored.

    • Gertjan

      Completely agree, this feature will be the seed for unconditionally nasty code.

  102. David

    Great features! Would there be patters for loops?

    foreach (var item in enumerable) where (item.Status = Active)
    //do it

    • Frank

      Can’t you just do this:
      foreach(var item in enumerable.Where(item => item.Status = Active)) {
      // do stuff here

  103. Cosmin Sontu

    Object expressions would be nice… or anonymous types that implement an interface or an abstract class

    var v = new IComparer where T: IComparable { CompareTo (x, y) => x.CompareTo(y) };

    • Hello, every time i used to check web site posts here in the early hours in the break of day, because i love to find out more and more.

  104. Peter Madsen

    Great to see the “switch statement with patterns”.
    Now I can retire my own “TypeSwitch” implementation 😉

    • Hurrah! Finally I got a website from where I know how
      to actually take helpful information concerning my study and knowledge.

  105. Wow. Espacially tuples are great as they also have the potential to improve performance and make for much cleaner code. The switch enhancements also look really interesting – but they make things considerably more complicated as you have to keep in mind to put the cases into the right sequence. I predict that this has potential for making mistakes. But the enhancements by the pattern where you can directly get the value are GREAT! Checking something and using it if the check is OK is a very common task and should be supported by the language. This is now the case for C# 7.
    You have spoken about performance improvements. But in the article I don’t see much information about it (I assume tuples will improve performance). Any figures about performance impact of these new features already available?
    Thanks for the great article and keep up the excellent work!

  106. Bas van der Linden

    Are there any thoughts on supporting deconstruction and result tuples in the Switch statements with patterns. E.g.:

    switch (point)
    case (var x, var y) when (x < 10):
    Console.WriteLine($"Yes: X = {x}, Y = {y}");
    case (var x, var y):
    Console.WriteLine($"No: X = {x}, Y = {y}");

  107. More and more of these C# language features are clearly the result of the F# language and its ongoing development. At some point this begs the question why continue with C# if its going to look more and more like F#. I’m not complaining I think C# is a great language but as I work with F# more and more and see its features creeping into C# the justification for using C# (at a linguistic level) is getting smaller every year.

    No doubt because many F# features are supported under the hood using .Net assemblies I suppose it’s “easy” to then add these to C#. The way things are going C# is going end up being simply F# with lots of extra braces and semicolons!

  108. Looking forward to pattern matching. Is there anyway to do pattern matching using a “method overload” instead of a switch statement? For example:

    public void DescribeShape(Rectangle s when (s.Length == s.Height)) {
    WriteLine($”{s.Length} x {s.Height} square”);

    public void DescribeShape(Rectangle s) {
    WriteLine($”{r.Length} x {r.Height} rectangle”);
    The most specific match wins. There should be someway to specify a default function to call in the case of no match.

  109. The scoping of out variables declarations and pattern matching declarations is drastically different from what Mads states here. He made a major change to scoping rules, stating that it was being asked for by everyone (no names given), and said that it’s a done deal, no discussion. You can read about it here:


    Moving forward, it will be impossible to know what variables are in scope.

  110. ellongrey

    What will happen if I ref return a field of temporary object?
    Could that be safe after the object is collected by GC?


    class Foo
    public int value;

    static ref int GetFieldOfTempObj()
    var temp = new Foo();
    return ref temp.value;

    static void Curious()
    ref int tempField = GetFieldOfTempObj();

    // Good bye temp obj~

    // Is this safe?

    • ellongrey

      Oops I should correct my question:

      I mean ‘GC.Collect()’ not ‘System.GC()’ (what was that language? @_@)
      and I should call ‘ref GetFieldOfTempObj()’ not just ‘GetFieldOfTempObj()’ according to above spec. >_<

  111. From your example on pattern matching/variables early on, how is “if (o is null)” different from “if (o == null)” ?

  112. Any chance Entity Framework will be adding support for tuples inside query expressions along with the C# 7 introduction of first-class tuples?

    The lack of support for this is super frustrating, especially since anonymous classes are not supported in EF either, though from a performance perspective this is simply a fixed number of values being passed into a query (ie: should not be any more complex to execute on the DB).

    Issue here: http://stackoverflow.com/questions/17595105/use-tuples-with-entity-framework-contains-statement

  113. Michael Powell

    Wow, so, yes C# 6 features just barely digested, and some frequently in use, like expression bodied members, string interpolation and the nameof operator (long time in coming on that little operator if you ask me). And now new C# 7 features, wow!

    Question re: the tuples. What would the signature look like for those, in terms of Func or anonymous delegates?


  114. Jared Van Leeuwen

    When started reading to part of about Is-expressions I was hoping that I could do
    if(o is MyType){

    But this is close enough I know I’ll use it.

  115. Tuples are nice but they would be even better with typdef:

    e.g. Would be nice to write:

    Complex = (float Re, float Im);
    Complex z = (3,4);

    And would be nice to have an var for member functions:

    var z = (int x,(int y,int z) b) => ((x,x),(b.y,-b.z))

    or have the names in the return value:

    var z = (int x,(int y,int z) b) => ((x:A,x:B):C,(b.y:D,-b.z:E):F)

    and it is a bit odd that the order is backwards when referencing e.g. b.z

    this is because c# has the format
    [type] [variable]

    instead of

    Maybe there should be an operator such that

    A.b.c == c@b@A

    @ could be read “of”. So that cat.color would be color@cat “color of cat”

    Just some suggestions for c# 8

  116. Pradip Kumar Das

    This is good place to know about the new language features of C# 7.0. Is there any Microsoft official site that documents these features? I tried to fine one, but could not. If anyone of you know about such official site, please let me know.

  117. Michael Puckett

    This probably isn’t the right place to post but I will here for now.
    I’m a big fan of C#, it’s by far my favorite language and I really like the direction it’s heading.
    However; if I may critique some, I believe there needs to be a greater level of testing / reviewing before presenting an official release. Nothing’s perfect, specially not my code, but the one thing I have always been able to rely on is that it was MY code causing the problem. With C# 7, it has presented a plethora of bugs that are related just to the language itself. There are areas that are incomplete, some that work only in set scenarios where they should work in all, and Visual Studio can’t even decide on the correct fix / simplification to use.
    C# 6 seems to be stable, at least I personally haven’t had any issues but I jumped into C# 7 right away, full code base refactoring, because I’ve always been able to rely on it and honestly it feels like I’m working in a beta. This is a REALLY BAD move for a strong and stable language and it’s going to bring the C# reputation from amazing to crap in just a couple of updates if it’s not handled immediately.
    I’ve been developing for a long time and I know it’s a tough business with lots of room for bugs and headaches, so I’m not saying I could have done better, but I am saying that something as critical as the actual source code syntax should require a bit more observing before going into a final release. This is the foundation of everyone’s hard work, where it starts, how it’s read and modified, and as the language improves so does our work… But we need to get a handle on it now… There are now even more questions unfolding with C# 7 like is it now compiling as efficiently, meaning are we handling the stack the same and in an efficient manner and should we update to C# 8 or 7.1 or whatever to fix the bugs we have now only to introduce new bugs or just let C# 7+ become it’s own force and stick with C# 6 where it’s safe?
    I’m trying not to rant and hopefully this doesn’t offend anyone because I personally care about the language and if I was offered the job believe me I would bust balls to make it stable and the best I could (again, not that I could do better) but there should be a comprehensive checklist of changes and how they are effected and the various ways to test them before approving them as release.

  118. Velan

    Actually, pattern matching is a great addition. Doing C# professionally and knowing a bit of Haskell, I’ve always wanted that C# has pattern matching on the shape of data. I’ll give it a try, thank you

  119. Looking forward to pattern matching. Is there anyway to do pattern matching using a “method overload” instead of a switch statement? For example:

    public void DescribeShape(Rectangle s when (s.Length == s.Height)) {
    WriteLine($”{s.Length} x {s.Height} square”);

    public void DescribeShape(Rectangle s) {
    WriteLine($”{r.Length} x {r.Height} rectangle”);
    The most specific match wins. There should be someway to specify a default function to call in the case of no match.

  120. Completely agree. VB.NET must die, because it is a complete waste of human resources. After that it would be good to focus on slowly killing JavaScript by replacing it with C# running in limited functionality mode. Web browers could check C# code to make sure that all methods are allowed and compile it on the client side. I really would like for cross-platform browers to use Mono and start supporting this tag on cliend side:

    Imagine posibilities. It would be so easy to extend it by just unlocking current libraries of C# on the client side. For example various math libraries which are safe to use from security point of view.

  121. Love the tuple literal idea.

    Wouldn’t it make more sense to have the name of the item in the tuple be the identity defining aspect, instead of the order?

    For example: suppose NextEmployee() is some library method that I don’t have the source code of, and isn’t particularly well documented, and suppose it returns (firstname: “jamie”, lastname: “hince”, id: 102348) to me, and I say:

    (string lastname, var _, int __) = NextEmployee(); // I only need the last name

    The compiler would either happily assign firstname to lastname, or warn or error about it. Why not just map lastname to lastname?

    I’d see that allowing for more loosely coupled architecture, if we didn’t have to remember the index of lastname in the tuple, and could just ask for an aspect “lastname” like that.

  122. Thank you for posting the great content…I was looking for something of C# 7.1 …I found it quiet interesting, hopefully you will keep posting such blogs on new updates …keep sharing.

  123. Anonymous
    (The content was deleted per user request)
  124. public void PrintCoordinates(Point p)
    int x, y; // have to agario“predeclare”
    p.GetCoordinates(out x, out y);
    WriteLine($”({x}, {y})”);

Comments are closed.