SO Vault: What do these new C# 6 features do?

0

Full article

StackOverflow sees quite a few threads deleted, usually for good reasons. Among the stinkers, though, lies the occasionally useful or otherwise interesting one, deleted by some pedantic nitpicker - so I resurrect them. πŸ‘»

Note: Because these threads are older, info may be outdated and links may be dead. Feel free to contact me, but I may not update them... this is an archive after all.


What do these new C# 6 features do?

Question asked by Michael on Apr 05, 2014

The language feature implementation status page of the Roslyn project lists several implemented or planned features of C# 6. I couldn't find any information on what some of them mean though.

What are:

  1. Dictionary initializer:

    new JObject { ["x"] = 3, ["y"] = 7 }
  2. Indexed member initializer:

    new JObject { $x = 3, $y = 7 }
  3. Indexed member access:

    c.$name = c.$first + " " + c.$last;
  4. Expression-bodied members:

    public double Dist => Sqrt(X * X + Y * Y);
  5. Event initializers:

    new Customer { Notify += MyHandler };
  6. Semicolon operator:

    (var x = Foo(); Write(x); x * x)
  7. Params IEnumerable:

    int Avg(params IEnumerable<int> numbers) { … }
  8. NameOf operator:

    string s = nameof(Console.Write);

Comments

I'll admit, I wasn't expecting to see $ make its way into C# identifier syntax. – BoltClock♦ Apr 5 '14 at 13:25

C# seems to be taking the path of making the language more expressive by introducing a lot of special cases to the syntax and semantics, instead of opting for more light weight and general approaches (not that it's necessarily bad). – Erik Allik Apr 5 '14 at 13:27

Well, #5 seems pretty obvious to me. Normally in object initializers, you can only set the values of fields/properties. Now you can also wire event handlers. (EDIT: yay!) – Chris Sinclair Apr 5 '14 at 13:38

Just watch the video of the Build Conference session, "The future of C#". Ask only one question per post. – Hans Passant Apr 5 '14 at 13:41

#7 refers to the fact that you can create a params array input. These methods also mean that in addition to passing in variables like myMethod(0, 1, 2, 3) you could pass it in as an array: int[] myInput = new []{0, 1, 2, 3}; myMethod(myInput); But it had to be an array. With "params IEnumerable", I would assume it's pretty much the same behaviour as "params Array" but you could then pass in any IEnumerable<T> instead of being forced to use arrays. IEnumerables tend to be more common than arrays so this is a nice convenience. – Chris Sinclair Apr 5 '14 at 13:43

@HansPassant: Conveniently, it looks like the video of that session isn't up yet at: channel9.msdn.com/Events/Build/2014/2-577 (But I'm guessing it will be soon.) – Chris Sinclair Apr 5 '14 at 13:47

Some notes by Jon Skeet, the link to The future of C# @ Build and the Q&A with Anders Hejlsberg. – Jeroen Vannevel Apr 5 '14 at 14:52

@ChrisSinclair: If there were a way of using a single specification to attach events at construction and detach them at disposal, that would IMHO be a major win, especially if it could take care of detaching events when the constructor fails. Although one can often get away with attaching events and never detaching them, there's IMHO no reason that should have become common practice, but for the lack of proper language support for event cleanup. – supercat Apr 6 '14 at 21:10

This question is not ideal: Too broad, somewhat vulnerability to becoming out of date (these changes are not finalized). They're better addressed in a blog than on SO. That being said, the individual questions are all very precise syntax questions, so it's easily addressed. I won't vote to close, despite objectively thinking I ought to. – Brian Apr 8 '14 at 13:12

A couple days after this question was asked, the status page was updated. Now, directly above the feature table, there are links to pdf files describing the features in detail. – Brian Apr 9 '14 at 16:45

Please stop adding features to C#! ANSI C is simple, let C# to be simple. – Amir Saniyan Apr 10 '14 at 9:17

@AmirSaniyan - C# 1.0 was never intended to be the final form of the language. It's always been known that it was going to grow and change, and it should. – Maurice Reeves Apr 10 '14 at 16:49

I see that C# is still playing catchup to VB.NET - god, if i had to write in C# I would totally have no motivation to write software what-so-ever (at all), it would be a drag. If you're not using VB.NET, you don't know what you're missing out on. VB.NET has slightly more features than C# (all things included), as Jon Skeet himself has said previously. – Erx_VB.NExT.Coder Apr 13 '14 at 16:15

@BoltClock It's gone as of the 21st of Apr :) – Ondrej Janacek May 3 '14 at 10:21

That roslyn is openSource it's a good idea while MicroSoft c# & VB are not. – Bellash May 5 '14 at 11:54

It is truly amazing that this question is not only closed, but has a delete vote. Because yes, there are infinite possible answers to "what does the nameof operator do?" (wtf, this is C# not C Plus Equality) – McGarnagle Jun 27 '14 at 17:25

Some more features listed here and here. The compiler for v 6.0 will be Roslyn. – nawfal Jul 2 '14 at 21:21


Answer by Eric Lippert (Apr 05, 2014)

Dictionary, Index member and event initializers

Dictionary, indexer and event initializers are an extension of the collection and object initializer scenarios:

o = new Foo { A = 123 }; // object -- C# 3
c = new List<int> { 123 }; // collection -- C# 3
d = new Dictionary<int, int> { [1] = 2 }; // dictionary
j = new JSObject { $x = y }; // indexed
b = new Button { OnClick += handler } // event

is just a short way of writing:

temp = new Foo(); temp.A = 123; o = temp;
temp = new List<int>(); temp.Add(123); x = temp;
temp = new Dictionary<int, int>(); temp[1] = 2; d = temp;
temp = new JSObject(); temp["x"] = y; j = temp;
temp = new Button(); temp.OnClick += handler; b = temp; 

Indexed member access

Indexed member access now you can figure out:

j.$x

is just

j["x"]

Expression-bodied members

Expression bodied members:

int D => x + y;

is

int D { get { return x + y; } }

Semicolon operator

Semicolon operator is the sequential composition operator on expressions, just as semicolon is sequential composition on statements.

(M(); N())

means "evaluate M for its side effect and N for its value."

Params IEnumerable

Params IEnumerable is the ability to make params methods that take an IEnumerable<T> instead of a T[]. Suppose you have:

void M(params int[] p) { foreach(int i in p) Console.WriteLine(i); }

And now you have to say

M(myQuery.ToArray());

M doesn't use the fact that p is an array. It could be

void M(params IEnumerable<int> p) { foreach(int i in p) Console.WriteLine(i); }

And then

M(myQuery);

NameOf operator

Nameof operator is a weak form of infoof.

In Foof We Trust: A Dialogue

It's useful for logging code. If you have

void M() 
{
    Log("M called");

then if M is renamed you have to remember to change the string. But

Log(nameof(M) + " called" );

if M is renamed then either the renaming refactoring will change the symbol, or if you do it manually, the program will stop compiling until you fix it.

Comments

Ah, much better answers, but I'm not sad because of who posted it :). So I take it the semi-colon operator (with accompanying parentheses) is like the comma operator in C/C++? – J F Apr 5 '14 at 13:50

@JF: yes, it is the comma operator. – Eric Lippert Apr 5 '14 at 13:51

Great answer, just a couple of questions: 1. I'm not quite sure I understand the difference between indexed member and dictionary initializers. 2. What's the use case for the semicolon operator? – Michael Apr 5 '14 at 13:54

(1) I'm not quite sure I understand either. :-) I'm not yet convinced of the utility of the $ features; they seem to save three keystrokes. (2) the use case is for when you have something that can only go in an expression context but you want to produce a side effect in a particular order. It is a weak feature on its own but it combines very nicely with other features. – Eric Lippert Apr 5 '14 at 14:06

As I said below (darn you, Lippert, and your fast fingers!), the .$ operator is the same as the longstanding ! operator in VB. It's basically a very simple way to do expandos without having to support the huge amount of machinery you need for something more full featured like "dynamic", and covers most of the use cases you care about. (I always loved the ! operator and never thought it got the respect it deserved. Nice to see the C# team finally come around...) – panopticoncentral Apr 5 '14 at 14:28

@panopticoncentral: Hey Paul, good to hear from you. Indeed, the justification for the feature is that it is a lighter-weight "dynamic". – Eric Lippert Apr 5 '14 at 14:33

So if I have understood correctly, the new semicolon operator is just that horrible C and C++ comma operator? – Manu343726 Apr 5 '14 at 17:11

@Manu343726, yep, as Eric said in a comment above. – Michael Petrotta Apr 5 '14 at 18:12

It seems like it's supposed to be more permissive than C and C++'s comma operators: the example uses a declaration as its LHS. – user743382 Apr 5 '14 at 19:05

@hdv that's yet another new feature proposal, putting declarations in expressions. It works very nicely with the composition operator. – Eric Lippert Apr 5 '14 at 19:37

Is there anything you can do with the initializers, indexed member access, expression bodied members and the semicolon operator that you couldn't do with more or different code? They all seem like little syntactic shortcuts rather than new features. Or am I missing something? – Patrick M Apr 5 '14 at 20:47

@PatrickM: You can put them in contexts that expect only an expression, like a query comprehension. – Eric Lippert Apr 5 '14 at 21:16

I don't understand the dictionary initializer thing. The counterexamples that keep getting given are m = new Dictionary<int, int>(); m[1] = 2; and so on. But we already have a real dictionary initializer syntax: new Dictionary<int, int> { { 1, 2 }, { 3, 4 } }. Any idea why we needed another syntax for it? – Aaronaught Apr 6 '14 at 15:13

@Aaronaught: Are you guaranteed that all dictionary objects have an Add method that takes pairs? Suppose for example you have an object that represents an XML document where element["attr"] = "value" is legal. Do we have a guarantee that this object has a method Add that happens to take two strings and adds an attribute-value pair? It seems plausible that the author of that object neglected to implement such a method. – Eric Lippert Apr 6 '14 at 15:18

Fair enough. It's unfortunate that both of the examples that were chosen (Dictionary<TKey, TValue> and JObject) are both types that do have such a method and already support the existing initializer syntax. Are there no better examples in the BCL, where this alternative can't be used? – Aaronaught Apr 6 '14 at 15:34

I know you don't work there any more, but do you know if a.$name is refactorable? I.e. renaming it and only having it apply to the right object/property? – jmoreno Apr 6 '14 at 23:05

@jmoreno: I don't know; that's a good question. F# has a feature called "type providers" that might prove useful in such a scenario. – Eric Lippert Apr 7 '14 at 0:11

It is getting much harder to look at C# code and know what spellings are being checked by the compiler and what is not, e.g. a.$spalling looks like the compiler will check that spalling is valid, unless you are an expert. – Ian Ringrose Apr 7 '14 at 11:15

@IanRingrose If you're relying on your compiler to spellcheck for you, you're going to have a bad time... – Algorath Apr 7 '14 at 14:11

@Algorath, I like static typing, code that does not use static typing needs more rewiewing to trap that sort of error. I hope the "a" in a.$name can be a string constant. – Ian Ringrose Apr 7 '14 at 15:07

@EricLippert: Should design flaws (missing Add method) really be fixed by adding new language features? One of the design goals of C# was to create a simple language. Is C# simple? No. Every new feature added lets C# deviate more from this goal. – Olivier Jacot-Descombes Apr 19 '14 at 21:09

Can I have a vote to not implement the indexed member and expression bodied member sugars? Feels bit of deviation from C# syntax we are used to. And also semi-colon operator? The same thing can be done { M(); return N(); }. Not sure how much value it adds for the added syntax. Everything else looks awesome :) – nawfal Jul 22 '14 at 7:30

@nawfal: Sure, but a comment on StackOverflow isn't the right place. Join the roslyn forum on roslyn.codeplex.com if you want to express an opinion to the language designers. – Eric Lippert Jul 22 '14 at 13:43

@EricLippert thanks. I was seeing it. – nawfal Jul 22 '14 at 14:14

I think an even much better example for the benefit of using nameof than the logging use case is constructing a WPF Binding in code-behind. – O. R. Mapper Aug 19 '14 at 13:43


Answer by panopticoncentral (Apr 05, 2014)

Dictionary initializer

new JObject { ["x"] = 3, ["y"] = 7 }

Like the name says, this feature simplified initializing a dictionary (a.k.a. a hash table) in-place. For example, the above code would have to be normally written as a series of statements (a = new JObject(); a["x"]=3; a["y"]=7).

This is particularly useful when you want to immediately pass the dictionary as a parameter, initialize it as a part of construction, or use it as a part of a general object initializer (esp. for anonymous types).

Indexed member initializer

new JObject { $x = 3, $y = 7 }

This really just combines #1 and #3 (see below).

Indexed member access

c.$name = c.$first + " " + c.$last;

This is syntactic sugar for the index operator ([]). So c.$name is the same as c["name"]. This enables string indexing to look more like general property access. (FYI, this is basically the same as the ! operator that VB has had for forever.)

Expression-bodied members

public double Dist => Sqrt(X * X + Y * Y);

Syntactic sugar for simple function declarations. The example would currently be written as something like public double Dist { get { return Sqrt(X * X + Y * Y); } }.

Event initializers

new Customer { Notify += MyHandler };

This allows you to set up an event handler in the context of an object initializer. Today you'd have to write:

Customer x = new Customer { .Name = "Bob" };
x.Notify += MyHandler;

but now you can write it all inline.

Semicolon operator

(var x = Foo(); Write(x); x * x)

This is the equivalent of the comma operator in C -- you can string expressions together and the "value" of the expression is the last one. Like in the example, it allows you to inline declare a variable, do something with it, and then return another value from the expression.

Params IEnumerable

int Avg(params IEnumerable<int> numbers) { … }

Today a "params" parameter has to be an array, but if all you're going to do is enumerate the values of the parameter (i.e. you don't need a full array) and the argument you're passing in isn't an array (but is enumerable), you can save the array allocation and copy. Useful especially for LINQ scenarios.

NameOf operator

string s = nameof(Console.Write);

Useful for diagnostic or exception scenarios (like ArgumentException), where you want to print out or say the name of something that failed or wasn't correct but don't want to have to write it out in a string and have to make sure it stays in sync. Or in places where you're doing a notification that includes the name of the event/property that fired.

Comments

I added some formatting to your post considering it contains valuable content and this will be one of those popular questions. This will make it easier for people to skim through the different sections. – Jeroen Vannevel Apr 5 '14 at 14:44

Thanks so much! I was typing furiously in the hopes of getting ahead of the pack (again, darn that Lippert!) and was going to come back and do that. Much appreciated. – panopticoncentral Apr 5 '14 at 14:47

Wouldn't Dist => Sqrt(X * X + Y * Y) be a property? I think you should write Dist() => for a method. – Kobi Apr 6 '14 at 6:10

Just like the $x it can make string names of properties (for instance used for INotifyPropertyChanged) refactorable (you can rename the property and you do not have to worry about these references to follow. Up to .net 4 it took some large lambda expression to get the same effect. In the case of the $ syntax it still will have to match the fieldname but everything is better than magic strings when refactoring (or huge amounts of string constants). – wvd_vegt Apr 14 '14 at 8:28


Answer by J F (Apr 05, 2014)

1 & 2: shorthand for

new JObject
{
    new JProperty("x", 3),
    new JProperty("y", 3)
};

A more general example would be:

var dict = new Dictionary<string, int>
{
    $firstKey = 4,
    ["a second key"] = 9
};

instead of

var dict = new Dictionary<string, int>
{
    { "firstKey", 4 },
    { "a second key", 9 }
};

In this case it's not really terser, but depending on how well it does type inference, I suppose it can be.

3. related to 1&2, it's alternative syntax for

c["name"] = c["first"] + " " + c["last"];

4. shorthand for

public double Dist()
{
    return Sqrt(x * X + Y * Y);
}

5. I believe is shorthand for

var cust = new Customer();
cust.Event += MyHandler;

Previously, this type of initializer syntax didn't work for EventHandlers

6. Equivalent to C/C++'s comma operator. So this snippet:

var result = (A(); B(); C());

should do A(), then B(), and return the value of C() and store it in result.

7. alternate syntax for

int Avg(params int[] numbers) { … }

with the difference that this makes it possible for numbers to be evaluated lazily

8. will return the name of the symbol, so in that example, s == "Console.Write" (unsure if it'll return a fully qualified namespace or not)


Answer by Raja Nadar (Apr 05, 2014)

a few of the constructs explained.

  • "Dictionary initializer" (new JObject { ["x"] = 3, ["y"] = 7 })

This is a further shorthand to initialize a dictionary. previously:

Dictionary<string, string> foo =
       new Dictionary<string, string> { {"key1", "value1"}, {"key2", "value2"} };
  • "Expression-bodied members" (public double Dist => Sqrt(X * X + Y * Y);)

This is a further shorthand to set a property value using a getter method. The above code could previously be:

public double Dist
{
 get
 {
  return Math.Sqrt(X * X + Y * Y)
 }
}

In fact if you notice, there is no Math.Sqrt used in the 6.0 construct. The Sqrt is used directly. That itself is a feature called:

Importing all the public static methods of a type into your namespace when you do something like using Math;

  • "Event initializers" (new Customer { Notify += MyHandler };)

This is a shorthand for auto-initializing event properties now. previously it would be:

Customer foo = new Customer();
foo.Notify += MyHandler; // Notify is the event property of the object.
  • "Params IEnumerable" (int Avg(params IEnumerable<int> numbers) { … })

Previously we had to declare params parameters as array. This would mean the caller had to send the evaluated array to the method.

public int MyMethod(params int[] arg)
{
 return 0;
}

had to be called as

MyMethod(new myarray[] {1,2,3}); // pre-evaluated array

with the new syntax, no more pre-evaluation.


Shared with attribution, where reasonably possible, per the SO attribution policy and cc-by-something. If you were the author of something I posted here, and want that portion removed, just let me know.

Author

Grant Winney

Is there anything more satisfying than sharing knowledge? Of teaching someone and witnessing their "ah ha" moment? I usually write about tech, but no promises. I hope you find something interesting!



Comments