New Features in C# 6
C# 6 is the version of C# that ships with VS 2015 Preview. The philosophy behind this version is straightforward: improve simple everyday coding scenarios, without adding much conceptual baggage. The features should make code lighter without making the language heavier.
Some features are mostly syntactic sugar (expression-bodied members, string interpolation, nameof), some complete what felt a bit like unfinished work (getter-only auto-properties, await in catch and finally) or expand existing features in a natural way (using static, index initializers). Some expose expressiveness from IL that C# didn’t previously surface (exception filters, parameterless constructors in structs). Some are almost just “bug fixes” to the design, and you’ll hardly know that you’re making use of them (improved overload resolution, extension Add methods in collection initializers).
In the following, I’ll take you through each of these language features. We’ll start at the expression level, and work our way “outwards”. We’re quite confident that this is the set that will end up in the shipping version, but we already know that some of them will change a little. I’ll let you know when we get there.
Expression-level features
nameof expressions are a new form of string literal that require more syntax and are more restricted than the existing kinds. What’s not to like?
Actually there’s a lot to like. Oftentimes you need to provide a string that names some program element: when throwing an ArgumentNullException you want to name the guilty argument; when raising a PropertyChanged event you want to name the property that changed, etc.
Using ordinary string literals for this purpose is simple, but error prone. You may spell it wrong, or a refactoring may leave it stale. nameof expressions are essentially a fancy kind of string literal where the compiler checks that you have something of the given name, and Visual Studio knows what it refers to, so navigation and refactoring will work:
(if x == null) throw new ArgumentNullException(nameof(x) );
You can put more elaborate dotted names in a nameof expression, but that’s just to tell the compiler where to look: only the final identifier will be used:
WriteLine(nameof(person.Address.ZipCode) ); // prints "ZipCode"
Note: there are small design changes to nameof since the Preview was built. In the preview, dotted expressions like in the last example, where person is a variable in scope, are not allowed. Instead you have to dot in through the type.
String interpolation lets you more easily format strings. String.Format and its cousins are very versatile, but their use is somewhat clunky and error prone. Particularly unfortunate is the use of numbered placeholders like {0} in the format string, which must line up with separately supplied arguments:
var s = String.Format("{0} is {1} year{{s}} old", p.Name, p.Age);
String interpolation lets you put the expressions right in their place, by having “holes” directly in the string literal:
var s = " \{p.Name} is \{p.Age} year{s} old";
Just as with String.Format, optional alignment and format specifiers can be given:
var s = "\{p.Name ,20} is \{p.Age :D3} year{s} old";
The contents of the holes can be pretty much any expression, including even other strings:
var s = "\{p.Name} is \{p.Age} year\{ (p.Age == 1 ? "" : "s") } old";
Notice that the conditional expression is parenthesized, so that the ‘: "s"’ doesn’t get confused with a format specifier.
Note: This describes the syntax that works in the Preview. However, we’ve decided to change the syntax, to even better match that of format strings. In a later release you’ll see interpolated strings written like this:
var s = $"{p.Name,20} is {p.Age:D3} year{{s}} old";
Also we are adding a scheme so that you can influence the formatting behavior; e.g. to use Invariant Culture. More on this in a later post.
Null-conditional operators address many of the situations where code tends to drown in null-checking. They let you access members and elements only when the receiver is not-null, providing a null result otherwise:
int? length = customers ?. Length; // null if customers is null
Customer first = customers ?[ 0 ] ; // null if customers is null
The null-conditional operator is conveniently used together with the null-coalescing operator `??` to provide a default value for when the outcome is null:
int length = customers?.Length ?? 0; // 0 if customers is null
The null-conditional operator exhibits short-circuiting behavior, where an immediately following chain of member accesses, element accesses and invocations will only be executed if the original receiver was not null:
int? first = customers ?[0].Orders.Count() ; // if customers is null, the result is null
This example is essentially equivalent to:
int? first = (customers != null) ? customers[0].Orders.Count() : null;
Except that customers is only evaluated once. None of the member accesses, element accesses and invocations immediately following the ? are executed unless customers has a non-null value.
Of course null-conditional operators can themselves be chained, in case there is a need to check for null more than once in a chain:
int? first = customers ?[ 0 ] .Orders ?. Count();
Note that an invocation (a parenthesized argument list) cannot immediately follow the ? operator – that would lead to too many syntactic ambiguities. Thus, the straightforward way of calling a delegate only if it’s there does not work:
if (predicate ?(e) ?? false) { … } // Error!!
However, you can do it via the Invoke method on the delegate:
if (predicate ?.Invoke(e) ?? false) { … }
We expect that a very common use of this pattern will be for triggering of events:
PropertyChanged ?.Invoke(this, args);
This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable.
Index initializers extend object initializers so that you can now initialize not only members but also indices of the newly created object:
var numbers = new Dictionary<int, string> {
[7] = "seven" ,
[9] = "nine" ,
[13] = "thirteen"
};
A common use for this would be for creating Json objects declaratively in one expression, rather than having to first create the object and then assign into it in separate statements.
Extension Add methods are now observed in collection initializers; we used to only recognize instance methods called Add. Just a design fix; VB already does this.
Overload resolution has been improved in a few ways, which will likely result in more things just working the way you’d expect them to. The improvements all relate to “betterness” – the way the compiler decides which of two overloads is better for a given argument.
One place where you might notice this (or rather stop noticing a problem!) is when choosing between overloads taking nullable value types. Another is when passing method groups (as opposed to lambdas) to overloads expecting delegates. The details aren’t worth expanding on here – just wanted to let you know!
Statement-level features
Exception filters are a CLR capability that is exposed in Visual Basic and F#, but hasn’t been in C# – until now. This is what they look like:
try { … }
catch (MyException e) if (myfilter(e))
{
…
}
If the parenthesized expression after ‘if’ evaluates to true, the catch block is run, otherwise the exception keeps going.
Exception filters are preferable to catching and rethrowing because they leave the stack unharmed. If the exception later causes the stack to be dumped, you can see where it originally came from, rather than just the last place it was rethrown.
It is also a common and accepted form of “abuse” to use exception filters for side effects; e.g. logging. They can inspect an exception “flying by” without intercepting its course. In those cases, the filter will often be a call to a false-returning helper function which executes the side effects:
private static bool Log(Exception e) { /* log it */ ; return false; }
…
try { … }
catch (Exception e) if (Log(e)) {}
Await in catch and finally blocks has been disallowed until now. We’d somehow convinced ourselves that it wasn’t possible to implement, but now we’ve figured it out, so apparently it wasn’t impossible after all.
This has actually been a significant limitation, and people have had to employ unsightly workarounds to compensate. That is no longer necessary:
Resource res = null;
try
{
res = await Resource.OpenAsync(…); // You could always do this.
…
}
catch(ResourceException e)
{
await Resource.LogAsync(res, e); // Now you can do this …
}
finally
{
if (res != null) await res.CloseAsync(); // … and this.
}
The implementation in the compiler is quite complicated, but you don’t have to worry about that. That’s the whole point of having async in the language: so that most of the complicated stuff is left to the compiler.
Member declaration features
Auto-property initializers are now enabled, and are similar to initializers on fields:
public class Customer
{
public string First { get; set; } = "Jane";
public string Last { get; set; } = "Doe";
}
The initializer directly initializes the backing field; it doesn’t work through the setter of the auto-property. The initializers are executed in order as written, just as – and along with – field initializers.
Just like field initializers, auto-property initializers cannot reference ‘this’ – after all they are executed before the object is properly initialized.
Getter-only auto-properties allow you to omit a setter on an auto-property:
public class Customer
{
public string First { get; } = "Jane";
public string Last { get; } = "Doe";
}
The backing field of a getter-only auto-property is implicitly declared as readonly (though this matters only for reflection purposes). It can be initialized through an initializer on the property as in the example above, or it can be assigned in the declaring type’s constructor body, which causes the value to be assigned directly to the underlying field:
public class Customer
{
public string Name { get; };
public Customer(string first, string last)
{
Name = first + " " + last;
}
}
This is about expressing types more concisely, but note that it also removes an important difference in the language between mutable and immutable types: auto-properties were a shorthand available only if you were willing to make your class mutable, and so the temptation to default to that was great. Now, with getter-only auto-properties, the playing field has been leveled between mutable and immutable.
Expression-bodied function members allow methods, properties and other kinds of function members to have bodies that are expressions instead of statement blocks, just like with lambda expressions.
Methods as well as user-defined operators and conversions can be given an expression body by use of the “lambda arrow”:
public Point Move(int dx, int dy) => new Point(x + dx, y + dy) ;
public static Complex operator +(Complex a, Complex b) => a.Add(b) ;
public static implicit operator string(Person p) => "\{p.First} \{p.Last}" ;
The effect is exactly the same as if the methods had had a block body with a single return statement.
For void returning methods – and Task returning async methods – the arrow syntax still applies, but the expression following the arrow must be a statement expression (just as is the rule for lambdas):
public void Print() => Console.WriteLine(First + " " + Last) ;
Properties and indexers can have getters and settersgetter-only properties and indexers can have an expression body:
public string Name => First + " " + Last ;
public Customer this[long id] => store.LookupCustomer(id) ;
Note that there is no get keyword: it is implied by the use of the expression body syntax.
Parameterless constructors in structs are now allowed:
struct Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age) { Name = name; Age = age; }
public Person() : this("Jane Doe", 37) { }
}
The expression ‘new Person()’ will execute the declared constructor instead of the standard behavior of providing the default value. Note, however, that ‘default(Person)’ will still produce the default value, as will ‘new Person[…]’ for each of the array elements. In those cases the constructor is not executed: It’s only when you explicitly use ‘new’ on the struct type.
Import features
using static is a new kind of using clause that lets you import static members of types directly into scope.
In the Preview it looks like this:
using System.Console;
using System.Math;class Program
{
static void Main()
{
WriteLine(Sqrt(3*3 + 4*4));
}
}
This is great for when you have a set of functions related to a certain domain that you use all the time. System.Math would be a common example of that.
Note: The Preview will only import members of static classes. We have since changed the design in several ways:
- The syntax will be more different from current using clauses – it will have the keywords “ using static ”.
- Members of non-static types can be imported, including structs and en ums
- Members of VB modules and F# top level functions can be imported
- Extension methods will not be imported into top-level scope; instead they will show up as extension methods. This gives a way to import extension methods from just a single class, something which wasn’t possible before.
Want to try it out?
Download VS 2015 Preview and tell us what you think. Happy Hacking!
Mads Torgersen, Principal Program Manager, VS Managed Languages
Mads is the PM for the C# programming language at Microsoft. He runs the design meetings and maintains the language specification. He is also involved in the design of Visual Basic and TypeScript.
Comments
Anonymous
November 20, 2014
The comment has been removedAnonymous
November 20, 2014
@Jargon, I'm wondering the same thing. It seems like it is conditional and might replace the parenthesized conditional expression. Regardless, "string interpolation" seems more intuitive.Anonymous
November 20, 2014
"Note, however, that ‘default(Person)’ will still produce the default value, as will ‘new Person[…]’ for each of the array elements. In those cases the constructor is not executed: It’s only when you explicitly use ‘new’ on the struct type." Wouldn't this cause more confusion? Mads, can you elaborate why this behavior was chosen?Anonymous
November 20, 2014
Will be there string interpolation for verbose strings?Anonymous
November 20, 2014
not much improvement but its best everAnonymous
November 20, 2014
There is nothing in this new version of C# that I don't like. =)Anonymous
November 20, 2014
"This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable." It's not thread-safe because the JIT is allowed to reload the temporary local from memory. Nothing in the CLR memory model prevents this transformation. The local can be replaced by the field the delegate came from (maybe to save a local and prevent spilling).Anonymous
November 20, 2014
Those last three I think will be more confusing than good. Never typed a code and thought "how good it be if we have this". But certainly Null-conditional operators and String interpolation is a huge step forward. Will use it a lot.Anonymous
November 20, 2014
The comment has been removedAnonymous
November 20, 2014
Another problem with struct default ctors: They are not invoked when instantiating a generic type parameter: where T:new(); //... new T(); //uses initblk It is really random when this ctor is being invoked and when not. I can only predict it because I know some low level details about how IL and the CLR work.Anonymous
November 20, 2014
What do you mean by "Members of non-static types can be imported, including structs and enums " ? Importing nested types ?Anonymous
November 20, 2014
What happens if an exception filter throws? Am I right thinking that the original exception is hidden behind the new one?Anonymous
November 20, 2014
The comment has been removedAnonymous
November 21, 2014
The comment has been removedAnonymous
November 21, 2014
The comment has been removedAnonymous
November 21, 2014
@Sinix: I think you mean "verbatim" strings? Yes we plan to let you interpolate a verbatim string as well. That's good if you want to specify a file path or a regular expression, and you don't want to have to escape all the backslashes: var path = $@"{basedir}{user}configsettings.txt"; Of course it starts looking a bit like your code is swearing at you, but we felt it was worth it, and reasonably intuitive. Yes, we did have a bit of an argument about whether it should be "$@" or "@$" or both - do you interpolate a verbatim string or verbatim an interpolated string? :-)Anonymous
November 21, 2014
@Yuval and others, regarding parameterless constructors on structs: the thing to realize is that, before and now, constructors don't necessarily run on structs. All we did was add the ability to have an parameterless constructor that also cannot be guaranteed to run. There is no reasonable way to have structs that are guaranteed to have been initialized, and parameterless constructors don't help with that. The thing parameterless constructors help with is allowing you to have a parameterless constructor. I think a main source of confusion is that 'new S()' is allowed to mean 'default(S)'. That is a historical mistake in the language and I dearly wish I could take it away. I would strongly discourage anyone from using 'new S()' on a struct that doesn't have a parameterless constructor. As far as I can tell, this is in because the default(S) syntax didn't exist in C# 1.0, so this was just the syntax used for getting a default value of a struct. It is true that the compiler implementation has so far "optimized" 'new T()' to mean essentially default(T) when T is a struct. That was actually a bug - it was always supposed to call an actual parameterless constructor if there is one - which there could have been all along, since it is allowed in IL. We are fixing this, so that we will call the constructor even in the generic case. The semantics therefore is clean: new S() is the only way to run a parameterless constructor on a struct, and it always runs that constructor - even through generics.Anonymous
November 21, 2014
@xor88: the pattern is thread safe despite rumors of the opposite! :-) It is true that the CLR memory model, as defined by the ECMA standard, allows some optimizations that would break this. However, no implementation today currently makes those optimizations, and there's a lot of code out there that depends on them not being made, so any hypothetical implementer who would actually make them, would be met by an outcry. I think this belongs in the ECMA spec as a guarantee. The CLI folks aren't active now, so I don't know if it will happen in practice. I do have assertions from the CLR team at Microsoft that the assumptions making the pattern thread safe will never be broken by their implementations. BTW, I'm told that those optimizations wouldn't yield much of a performance benefit anyway.Anonymous
November 21, 2014
@Jiří: I meant that we want to allow importing static members (and nested types) from any kind of type, not just from static classes. So you can import String and get the Format method. Or an enum type and get its members. Etc. To make it a little more clear that that's what you're doing, we're adding the "static" keyword. Read "using static" as "using the static members of".Anonymous
November 21, 2014
@Tom: great question! I had to go try it out myself. It seems that an exception thrown in the filter is lost, and the filter is considered to be false, but this is just based on my own quick test, which is here: try { Func<string, bool> Throw = msg => { throw new Exception(msg); }; try { throw new Exception("A"); } catch (Exception e) if (Throw("B")) { WriteLine("Inner catch: {e.Message}"); } } catch (Exception e) { WriteLine("Outer catch: {e.Message}"); } This prints out "Outer catch: A", which I take to mean that the "B" exception didn't make it out of there.Anonymous
November 21, 2014
I didn't notice any mention of Primary Constructors. Did you just not address those in this post, or did you decide not to include them in C# 6 after all?Anonymous
November 21, 2014
@James: we cut primary constructors. More details can be found here: roslyn.codeplex.com/.../568820Anonymous
November 21, 2014
@Mads, I have to agree with @Yuval and others, exposing parameterless constructors for structs that are only invoked by "new T()" syntax, and not "default(T)", arrays, etc. is just asking for trouble. Your arguments about how this isn't really a change may seem convincing to the internal C# team at MSFT who are familiar with the historical design intentions and the underlying IL, etc., but to the rest of us who use the language, it is already firmly established that structs do in fact already have a parameterless constructor, and it is consistently called in all cases. From the standpoint of our mental model of the language, then, this is a breaking change, since we now need to start thinking of "new T()" as a function call, and "new T[42] and default(T)" as special cases that does not make this call. Please remove or consider redesigning this confusing and neglibly useful feature.Anonymous
November 21, 2014
I have to agree with many others that my first reaction to parameterless constructors on structs was "not worth the potential for confusion." I read your earlier reply, Mads, about developers treating new X() and default(X) as interchangeable and I agree that using default(X) to mean "the default value of the struct" consistently would be great. My thought is this -- would you consider making this a warning in the compiler? "new X() used when there is no parameterless constructor declared for X". Or perhaps we could get it in as an FxCop rule or something...Anonymous
November 21, 2014
@Mads Thanks for the clarification on the curly braces. Looking forward to these changes, going to make everything nice and clean, especially those null conditional operators.Anonymous
November 21, 2014
Ouch. The string interpolation syntax is still PITA. To type {} on most non-us keyboard requires probably 6 key presses and two hands. Contrast this to this syntax: "§p.Name §p.Age" Just 1 keypress vs 6 with no shift keys involved.Anonymous
November 21, 2014
@Aaron: Good idea. Adding a warning to the language would be a breaking change, but someone should write and share a Roslyn diagnostic to that effect.Anonymous
November 21, 2014
Hello Mads! I'm asking if you could please provide a status update for roslyn.codeplex.com/.../69 "Regression: XML documentation respects accessibility now?" This issue is preventing me from compiling my solution (100+ projects) with any release of VS14/VS2015 to date. I really would love to try the performance of the new environment and run our test suite look for other regressions. Best regards, MichaelAnonymous
November 22, 2014
Mads, you wrote that the readonly declaration of a getter-only auto-property's backing field only matters for reflection purposes. That doesn't seem like it ought to be the case. The .NET (and C#?) optimizers should take advantage of readonly fields. Knowing that the field is readonly should allow the generated instructions to omit certain loads of the field's value. For example, if the method loads a field value into a register and later in the method (even after a sequence point) needs the same field value, the value in the register can still be used.Anonymous
November 22, 2014
@Mads. So regarding language features. What are the chances of getting a "with" statement like VB that is natively provided. I am in agreement with many that most of C# language is more elegant than VB, but it seems by now this would have been added. I know there is a religious debate among C# folks on this one, but I am of the opinion that it would enhance code reading and understanding rather than the opposite. Some argue that it would make it more difficult to read with a VB "With" equivalent. www.codeproject.com/.../C-equivalent-of-VB-s-With-keywordAnonymous
November 23, 2014
I like the new string interpolation version. Writing $"..." it will prevent us of having to write { repeatedly. Thumbs up! btw... where is the Primary Contrutor? Have I missed something? Sorry...Anonymous
November 23, 2014
"String interpolation" is misleading. It should be renamed to "string substitution".Anonymous
November 23, 2014
The new features are from new Apple's Swift languageAnonymous
November 24, 2014
I have 3 concerns with Exception Filters:
- The syntax feels inconsistent with the language even though the C# designers had the "foresight" to require that a block follow a catch statement rather than a block OR a statement.
- I have seen claims that this is new functionality because rethrowing exceptions muddies up the call stack and other exception state. If that is true (I have not seen it) then it is a bug to be fixed rather than a reason to add new syntax.
- Providing "goto catch" support patterned off the "goto case" support would feel more natural and provide more utility. Granted it requires a restriction that the target catch block must be for a less derived type than the 'current' containing catch block OR a risk of an InvalidCastException being thrown in the containing catch block. However, even the static/compile time restriction would cover most of the use cases (duplicated code in catch blocks) that I've seen.
Anonymous
November 24, 2014
Now if they could just add range conditional checking to cases in switch statements (effectively making them syntactically prettier else if's) my life would be complete.Anonymous
November 24, 2014
The comment has been removedAnonymous
November 25, 2014
Parameterless constructors in structs and using static features are a bit confusing for me but other things are great thanks!Anonymous
November 26, 2014
@Michael: Regarding work item 69: I've asked around and will get back with a status. Given that it's a holiday here, it may take a bit for me to get a reply.Anonymous
November 26, 2014
@Edward Brey: You are certainly right that we could take advantage of a readonly field for optimizations. I was being imprecise - what I meant was that there should be no observable semantic difference at the language level.Anonymous
November 26, 2014
@ECM_Guy: So far we've decided against having a with-like statement in C#. As you mention, there are arguments on both sides - I am sure that we'll debate it again. :-)Anonymous
November 26, 2014
@Celso: Glad that you like the $"..." syntax. Sorry about primary constructors, they were cut from C# 6. We want to think about syntactic shorthands for "record-like" types more holistically for C# 7. See here: roslyn.codeplex.com/.../568820Anonymous
November 26, 2014
Hello Mads! Thanks for the update. That's great to know :) I'll check with the thread next week. Happy Thanksgiving! MichaelAnonymous
November 29, 2014
Why did you change for string interpolation? I think it was much better before... I don't want C# to be PHP, just adding new syntax and symbols for every little feature like this and bloating the language, and I hate seeing the $ sign thanks to these languages.Anonymous
November 30, 2014
WriteLine(nameof(person.Address.ZipCode)); // prints "ZipCode" What if Address is null? Is nameof resolved at compile time, so actual instances don't matter or is it executed during during runtime and vulnerable to NullReferenceException?Anonymous
November 30, 2014
Will it be possible to explicitly implement a setter or getter and leave the other part implicit? For example, in current code it would look like this MyType _theObject; MyType TheObject { get { return _theObject; } set { _theObject = value; DoSomeMoreStuff(); } } What I'd like to have would be this: MyType TheObject { get; set { SyntaxToStoreTheActualValue; DoSomeMoreStuff(); } } or MyType TheObject { get { DoSomethingElse(); return SyntaxToReturnTheActualValue; } set; }Anonymous
November 30, 2014
The syntax to my last comment could look like this: MyType TheObject { get; set { set; DoSomeMoreStuff(); } } or MyType TheObject { get { DoSomethingElse(); get; } set; }Anonymous
December 01, 2014
@Neme: Why did we change string interpolation from "...{...}..." to $"...{...}..."? This change accomplishes two things: a) it lets us use the exact same syntax inside the string as in String.Format, so that it's easier to understand, and to switch between them b) it lets us have a verbatim version $@"...{...}...". The other syntax didn't allow that, because {...} is already allowed inside a verbatim string, and means nothing special. I'm sorry that those other languages poisoned $ for you. Maybe repeated use of string interpolation in C# can help you detox? :-)Anonymous
December 01, 2014
@DJ Doena: In WriteLine(nameof(person.Address.ZipCode)); // prints "ZipCode" What if Address is null? It doesn't matter. The expression inside the nameof is considered unreachable, and is never evaluated. For the same reason, the expression also doesn't have to be definitely assigned. Nameof works regardless. As for auto-properties where only one of the accessors is generated, as you mention we would need syntax for getting or setting the underlying field from the manually implemented accessor. So far we haven't found that to be worth it - we don't add new syntax lightly.Anonymous
December 03, 2014
@DJ Doena, More understandable would be to allow declaring the backing variable inside the property, e.g. MyType TheObject { MyType object; get {DoSomethingElse(); return object;} set {object=value; DoSomeMoreStuff(); } } This way, it would still be inaccessible outside the property definition, yet require little new syntax.Anonymous
December 04, 2014
@Anders That's a great idea, and one that comes up frequently. It's a little thing, but I think it'd be useful for properties and indexers. I'd like to add that some day.Anonymous
December 04, 2014
C# is such a great progressive language. Finally Microsoft are taking on board ideas from the industry. Microsoft really need to make more investment into getting C# platform independent i.e non-windows., I know there is mono but if they can start getting more large corporates on board to use c# as a server side language on a non-windows platform then I'd say in 5-10 years Java would be more or less dead.Anonymous
December 06, 2014
The comment has been removedAnonymous
December 08, 2014
I agree with xor about the parameterless constructor in structs. I personally don't like the $"adasfasd" way to interpolate strings. It reminds me of Scala where we have s"" or f"" or even "".format ways to do the same thing. Sometimes, we need to just go back to the start of the string to put a symbol to get the formatting option. I think that the "{hello}" or the "$hello" is a better way of do that, and a lot of languages like kotlin, php, python and groovy already uses this way and it works. I really liked the primary constructor, even in Scala or Kotlin, too bad that is was taken out. I had expected some others features like extension properties, some syntax sugar to invoke extension methods without the this keyword or even some ways to create better DSL structures, like this way kotlinlang.org/.../lambdas.html. Anyway, about the rest, I am really enjoying the changes! Congratulations!! XDAnonymous
December 11, 2014
@Anders: we are thinking about ways to better support immutability. I hope this is a theme that we can explore for C# 7.Anonymous
December 11, 2014
Getting this new feature is awesome! Thanks a lot!Anonymous
December 15, 2014
In this example: finally { if (res != null) await res.CloseAsync(); // … and this. } could the null conditional operator be used like this? await res?.CloseAsync();Anonymous
December 19, 2014
i want oops concepts in c#.net with examples pls reply meAnonymous
December 19, 2014
@Dave: No, we haven't made await null-conditional. I guess we could consider just generally allowing null as an operand to await; the outcome would be a no-op. I'm not sure I like that, though: often this would mask a bug where the operand was not supposed to be null. Something to think about! But not for C# 6. :-)Anonymous
December 28, 2014
On the idea of hybrid auto-properties. I have wished for this too. Property getters and setters already have a reserved name "value" that represents the object that is passed into or out of the property functions. We just need a reserved name like "prop" that represents the storage location of the auto-property. int MyTripple { get; set { prop = value % 3; } }Anonymous
January 03, 2015
Is there already a final documation on string interpolation or other new features?Anonymous
January 05, 2015
new features are similar to Funcional Programing language(like Haskel, Scala)Anonymous
January 06, 2015
Love all these new features and there's one more that, in my opinion, should have been implemented since the introduction of the Generics: the possibility to include parameter types in constructor constraints. That is, I should be able to do something like this: public static class Factory { public static T Create<T>() where T: class, new(string,int) { return new T("this is a sample string value", 2015); } } This would be much cleaner that having to use Activator.CreateInstance of having to invoke the constructor through Reflection.Anonymous
January 06, 2015
Love all these new features and there's one more that, in my opinion, should have been implemented since the introduction of the Generics: the possibility to include parameter types in constructor constraints. That is, I should be able to do something like this: public static class Factory { public static T Create<T>() where T: class, new(string,int) { return new T("this is a sample string value", 2015); } } This would be much cleaner that having to use Activator.CreateInstance of having to invoke the constructor through Reflection.Anonymous
January 11, 2015
No discriminated unions? :/Anonymous
January 11, 2015
Let me get this straight - a Program Manager owns the C# language specification, and is involved in the design of programming languages? Scary. Programming languages should be designed by practicing software developers, not "Program Managers".Anonymous
January 12, 2015
You can try all the released features (Latest Nuget) online here: volatileread.com/.../IndexAnonymous
January 14, 2015
This string interpolation is a nice feature. Unfortunately it is pretty useless. The reason is that most message where you use message patterns need to be localized. There is no way you can localize patterns used in string interpolation but you have to use String.Format and use a string pattern from .resx.Anonymous
January 15, 2015
Exciting list of new featuresAnonymous
January 21, 2015
int length = customers?.Length ?? 0; How is things like this leading us towards more readability? I mean seriously. I get the idea for wanting to make things shorter and to the point, but not at the cost of readability. Next thing you know we will have stuff like... int^ r* = Customers?.length*(<name>)# ?? 0; // Btw half this is made up And how is that going to serve the best interests of the community and those trying to learn the language?Anonymous
January 24, 2015
Syntax error in "if" condition: (if x == null) throw new ArgumentNullException(nameof(x)); It should be, if (x == null)Anonymous
February 03, 2015
Who is that "smarty" who implemented "static import"? Did he ever heard about "with" operator? "With" could be WAY BETTER than this moronic "import": with(obj1, obj2) { .PropFromObj1 = .FuncFromObj2(); }Anonymous
February 09, 2015
I just want to say THANK YOU for the null-conditional operator. After using SWIFT I almost couldn't come to C#.Anonymous
February 15, 2015
Not much new things but It is good rather than nothing :)Anonymous
February 17, 2015
Quick question. It's obvious that you guys are trying to reduce the cognitive charge upon whoever is programming/reading C#. A lot of things presented here are related to that it seems. On that lines, what about a binary conditional operator? Instead of: var s = "{p.Name} is {p.Age} year{(p.Age == 1 ? "" : "s")} old"; You could say: var s = "{p.Name} is {p.Age} year{(p.Age > 1 ?: "s")} old"; Note the (fictional) operator ?: after p.Age > 1. That reduces the code the minimum required, and properly optimised would avoid the string collation when p.Age == 1. Thanks! :) (side-note: I don't know if some of you missed Ben's comment on page 3, it's totally pertinent, no joke)Anonymous
February 17, 2015
I meant an unary conditional operator. Doh.Anonymous
February 20, 2015
I think that the Null-conditional will be a helpful one because of the error null ref exception.Anonymous
February 23, 2015
'Let me get this straight - a Program Manager owns the C# language specification, and is involved in the design of programming languages? Scary. Programming languages should be designed by practicing software developers, not "Program Managers".' That was rather rude and presumptuous. Just because he's a PM doesn't mean he doesn't know how to code.Anonymous
February 27, 2015
How would string interpolation work with resource files? By moving the variable name into the format string, the use cases for that string resource become limited to only the specific scopes that use the same variable names. So for example, if I've defined a string in my resx: <string name="age">{p.Name,20} is {p.Age:D3} year{{s}} old</string> How do I make my C# code use that resource?: var person = new Person(); Console.WriteLine(Resources.GetString("age"));Anonymous
March 09, 2015
Now that we have "using static", does it mean that it works only on static members? What about const inside classes (static or not)? Is PI directly usable after using static System.Math?Anonymous
March 09, 2015
I agree with F. Milando's comment. Actually a better implementation of generics constraints would probably have been more useful than some of the features introduced here. Rather than using reflection, it's possible to pass an Action method as parameter in order to instantiate a generic type without default constructor. However it would be cleaner to allow signature on a new() constraints. Also, it would also be great to have numeric constraint which would allow all numeric types. I don't get why such features are still not implemented 10 years after the generics introduction. Still, i appreciate very much the syntax simplification introduced here. I like condensed code, not so much because it's faster to type but rather because it helps to have a good overview on the global logic without having the mind busy with syntax or programming related issues. Take a look at a java class: you will have to scroll and scroll till you can review all the code, just because of the way properties accessors are implemented (or i should rather say not implemented). Now the equivalent c# class will take 3 times less lines of codes, and you can generally understand its general purpose at a glance.Anonymous
March 29, 2015
How to get database values using object without using Entities in Entity Framework? using (var db = new PhoenixDbContext()) { var obj = db.Database.SqlQuery<object>("Select * from [User]").ToList(); }Anonymous
April 04, 2015
Would it be possible to allow static variables in methods, like in VB.NET? public static void Test() { static var x = ...; } 'x' would be assigned a value only once here.Anonymous
April 05, 2015
looks promising, nice her and there little syntactic sugar that add up to a nice expressive language. And i thought the nameof/infoof would never see the light of visual studio, but here it is.Anonymous
April 15, 2015
Thanks for the great writeup, I will be sure to take in the information in this post. I was wondering why use nameof expressions when they just seem more complicated and not actually that much more useful than a string literal.Anonymous
April 19, 2015
The reason you use the nameof keyword is so that you dont have to change any code when somebody changes the name of the variable. Otherwise, you have to update it anytime someone refactors or changes the variable name. This happens all the time and exception messages don't get updated.Anonymous
April 21, 2015
The comment has been removedAnonymous
April 22, 2015
I find the using static feature of limited value. What would be more useful is a construct that is scoped to a code block and works with both instances or statics: //use the keyword "with" since "using" statement already exists var x = new Person(); with (x) { //assign property values .FirstName = "Freddie"; .LastName = "Mac"; //call methods .AddChild(new Person()); //nested with block with (.Children[0]) { .FirstName = "Sallie"; .LastName = "Mae"; } } //same construct for statics with (System.Console) { .Write("hello world"); .WriteLine("how are you doing?"); }Anonymous
April 22, 2015
I would like to have in c# the function that in Php is extract(), that creates array variables from an array. I think it's useful!Anonymous
April 23, 2015
I love those new features that ease my live. What about introducing (in next C# releases) some other syntaxic-sugar for function returning multiple output arguments. For instance: public [int x, double y] MyFunction(string toto) { ... } That would automatically translate to: public void MyFunction(out int x, out double y, string toto) { ... } And could be used like this: int x; double y; [x, y] = MyFunction("dummy");Anonymous
April 26, 2015
The comment has been removedAnonymous
May 27, 2015
Seems like developnment at Microsoft HQ has ground down to a haltAnonymous
June 04, 2015
There use to be a planned feature in C# 6 that would have make this possible: if (int.TryParse(input, out int result)) return result; instead of int result; if (int.TryParse(input, out result)) return result; but it seems that this feature is dropped from the final product :( May I know what is the background for dropping it?Anonymous
June 15, 2015
Good work with predicates...Anonymous
June 17, 2015
The comment has been removedAnonymous
June 30, 2015
Still far behind F#... but on the good way.Anonymous
July 07, 2015
Is there any improvements in using Switch Statements - BREAK, GOTO, DEFAULT, CASE Keywords!Anonymous
July 09, 2015
Much to say about it, but luckily I can be short... I completely agree with xor88.Anonymous
August 25, 2015
c# is becoming to unreadable let alone uncodeable. by that i mean there should by only 1 way to express a concept not multiple. some of the features are useful but some like primary ctors have been removed thankfully. also, why is a expression bodied member allowed but not expression bodied getter/setters. i can write public int SomeProperty => <expression> (readonly in this example) but not public int AnotherProperty { get => expression; set => method(); } i would have to add {} around each and the return for the getter. its only a {} and a return, but isn't that the point of the other allowed syntax? now empty methods and long methods need {} but if they are in the sweet spot can use =>. now some of the methods/properties if short enough use this new syntax but anything beyond that will probably use the existing syntax, that is inconsistent and its getting worse with each new release. i discovered the cobra language several years ago and felt like Salieri when he discovered Mozart (in the movie Amadeus) and wished he had never heard of him or seen his music.Anonymous
October 18, 2015
Nice crisp and clean article to explain the C# feature. Good Stuff!Anonymous
October 22, 2015
I'm trying a string interpolation like ..... $"test {x>0 ? x.ToString() : String.Empty}" ..... gives a syntax error on the colon. Is this possible to do?Anonymous
October 29, 2015
In 'using static' example first two lines should be: using static System.Console; using static System.Math; 'static' keyword is missing there. Please fix it for future visitors.Anonymous
December 03, 2015
The comment has been removed