Getting a sense of the upcoming language features in C#

Topics: C# Language Design
Coordinator
Jul 21, 2014 at 11:50 PM
Hi all,

As you saw, I posted some new and old design notes. I realize that keeping track of the intended language design based on incremental language notes is hard, especially when they are not published in order! In this case I put an older set of notes out so that I could reference them from the newer.

To get an overview of the full planned set of new C# language features, it is easier to check out "Upcoming Features in C#", which I just updated, so that it matches with CTP 2. I'll try to keep an up-to-date version linked from the Language Feature Status page as the implementation evolves.

I really recommend that you get hold of the CTP and play with it. More and more language features are making it in (null-conditional operator a?.b, expression bodied properties public double Dist => Sqrt(X * X + Y * Y);) or are getting into their final form (primary constructors). Remember to set the language version to 'experimental'; otherwise most features won't show up.

Happy hacking!
Coordinator
Aug 18, 2014 at 11:40 PM
Edited Aug 18, 2014 at 11:40 PM
Hi again,

Today we released CTP 3 of Visual Studio "14". There are a few more C# language features coming online, and I've updated the Upcoming Features accordingly:
  • The nameof operator - safe strings for named program elements, such as variables, types, members etc.
  • More expression-bodied function members - concise member bodies to avoid boilerplate when things are simple
  • Null-conditional statement expressions - easy null check when you raise events
Take them for a spin! And remember to turn on the "experimental" flag: the document tells you how.
Aug 25, 2014 at 5:52 PM
Hi,

"nameof" is really nice, I was able to use it as expected on classes, methods, events, properties and fields! One thing that's missing is the rename refactoring support! Tried the ctrl + . -> Rename 'Foo' to 'Bar', ranamed everything but it's "references" in nameof operator!

Thanks a lot for adding that kind of tools to c#!
Aug 25, 2014 at 8:15 PM
simonlbc wrote:
Hi,

"nameof" is really nice, I was able to use it as expected on classes, methods, events, properties and fields! One thing that's missing is the rename refactoring support! Tried the ctrl + . -> Rename 'Foo' to 'Bar', ranamed everything but it's "references" in nameof operator!

Thanks a lot for adding that kind of tools to c#!
Can you use it in a case of a switch statement? (AKA, is a constant expression?)
Aug 25, 2014 at 8:41 PM
madst wrote:
Today we released CTP 3 of Visual Studio "14". There are a few more C# language features coming online, and I've updated the Upcoming Features accordingly:
Looking at the indicated document, I saw no mention of when primary constructors and initializers are run relative to base-class initialization. Am I missing something, or was that information accidentally omitted?

Also, is it possible to have a public class with a primary constructor which is private or protected? If primary constructors can store parameters to fields before running the base-class constructor, that would represent an ability which is at present missing from C#; it should be possible to use that ability in a public class without having to make the public constructor itself public.
Aug 25, 2014 at 8:49 PM
Olmo wrote:
simonlbc wrote:
Hi,

"nameof" is really nice, I was able to use it as expected on classes, methods, events, properties and fields! One thing that's missing is the rename refactoring support! Tried the ctrl + . -> Rename 'Foo' to 'Bar', ranamed everything but it's "references" in nameof operator!

Thanks a lot for adding that kind of tools to c#!
Can you use it in a case of a switch statement? (AKA, is a constant expression?)
Just tried it, switch/case seems to work! :)
Coordinator
Aug 26, 2014 at 4:12 AM
simonlbc wrote:
Olmo wrote:
simonlbc wrote:
Hi,

"nameof" is really nice, I was able to use it as expected on classes, methods, events, properties and fields! One thing that's missing is the rename refactoring support! Tried the ctrl + . -> Rename 'Foo' to 'Bar', ranamed everything but it's "references" in nameof operator!

Thanks a lot for adding that kind of tools to c#!
Can you use it in a case of a switch statement? (AKA, is a constant expression?)
Just tried it, switch/case seems to work! :)
Can you post the code you had where rename didn't work? We expect it to.
Aug 26, 2014 at 4:46 PM
Edited Aug 26, 2014 at 4:47 PM
Pilchie wrote:
simonlbc wrote:
Olmo wrote:
simonlbc wrote:
Hi,

"nameof" is really nice, I was able to use it as expected on classes, methods, events, properties and fields! One thing that's missing is the rename refactoring support! Tried the ctrl + . -> Rename 'Foo' to 'Bar', ranamed everything but it's "references" in nameof operator!

Thanks a lot for adding that kind of tools to c#!
Can you use it in a case of a switch statement? (AKA, is a constant expression?)
Just tried it, switch/case seems to work! :)
Can you post the code you had where rename didn't work? We expect it to.
Sure thing, I used a vm in azure with latest vs ctp, no addition packages/extensions:

Try renaming Foo property to something else in here:
    public class SomeClass
    {
        public const string FooName = nameof(SomeClass.Foo);

        public int Foo { get;set; }
    }
But it works in here:
    public class SomeClass
    {
        public const string FooName = nameof(SomeClass.Foo);

        public static int Foo { get;set; }
    }
So, static property works, but instance property doesn't.

Or method here:
    public class SomeClass
    {
        public const string FooName = nameof(SomeClass.Foo);

        public static int Foo()
        {
            return 1;
        }
    }
doesn't work, and
    public class SomeClass
    {
        public const string FooName = nameof(SomeClass.Foo);

        public int Foo()
        {
            return 1;
        }
    }
doesn't work either. So rename refactoring doesn't work with static or instance methods.

Haven't tried with other member types (events and private members). I can give you access to the vm if you require it (again, if you get a brand new instance of "Visual Studio Professional 14 CTP 3" vm and do a new console app and try the rename refactoring, you should get the same behavior).
Aug 27, 2014 at 12:52 AM
The syntax for constructor body of primary constructor is ugly. like a soup of braces, which is hard to read and easy to mess up.
Hopes you can improve it before finalization.
Aug 27, 2014 at 11:33 AM
Edited Aug 27, 2014 at 11:33 AM
qrli wrote:
The syntax for constructor body of primary constructor is ugly. like a soup of braces, which is hard to read and easy to mess up.
Hopes you can improve it before finalization.
An example of an alternative syntax would be more helpful than just an opinion. Saying that, I generally agree and think that e.g. curly brackets here are unnecessary (e.g. see Scala):
//For these cases it is possible to specify a primary constructor body simply by enclosing it in curly braces 
//inside of the declared type:

public class Customer(string first, string last)
{
    {//Unnecessary and ugly
        if (first == null) throw new ArgumentNullException("first");
        if (last == null) throw new ArgumentNullException("last");
    }//Unnecessary and ugly

    public string First { get; } = first;
    public string Last { get; } = last;
}
Aug 27, 2014 at 1:14 PM
dsaf wrote:
An example of an alternative syntax would be more helpful than just an opinion. Saying that, I generally agree and think that e.g. curly brackets here are unnecessary (e.g. see Scala):
I think there should be a means of specifying which things should happen before base-class initialization, and which things should happen after (with the latter being able to make use of things in the base class). Further, as noted, I think the accessibility of the "primary" constructor needs to be separate from that of the class, but I haven't seen any mention of that. Am I the only one who sees the importance of that distinction?
Aug 27, 2014 at 1:30 PM
Edited Aug 27, 2014 at 1:34 PM
supercat wrote:
Am I the only one who sees the importance of that distinction?
I'd also like to be able to have a separate visibility for the primary constructor. F# allows it as well. As for initialization before/after the base class constructor runs: I know this is something that is very important to you, it's just that I've never encountered a real-world use case where I would've needed that. But I might just have been lucky.

However, this whole primary constructor thing gets even more useless if records make it into the language (see the records and pattern matching thread). It seems to me that most of the time you would use a primary constructor, you'd actually also want the other features that records provide you. But I guess we have to wait and see what the language design group thinks about the record/pattern match proposal, maybe that influences the design of primary constructors for arbitrary classes and structs.

Also, could we please get some details on the improved overload resolution mentioned in the upcoming features document? Especially when passing method groups (as opposed to lambdas) to overloads expecting delegates. What exactly has been improved? I've had a couple of problems with that in the past, I just can't recall the details at the moment.
Aug 27, 2014 at 8:44 PM
Expandable wrote:
I'd also like to be able to have a separate visibility for the primary constructor. F# allows it as well. As for initialization before/after the base class constructor runs: I know this is something that is very important to you, it's just that I've never encountered a real-world use case where I would've needed that. But I might just have been lucky.
I tend to believe that it's better to set field values using initializers than using constructors. In VB.NET, if a class includes:
ReadOnly FooLength As Integer = params.Length;  ' Use some trickery to get access to the constructor parameters
ReadOnly Foos As Foo(0 To FooLength-1) ' C# equivalent: readonly var foos = new Foo[FooLength];
those two lines together would establish an invariant that Foos will always be an array of size FooLength; that invariant will not be affected by anything else in the class. By contrast, if Foos were defined in a constructor, one wouldn't know whether that established an invariant unless one examined every single constructor that might exist for the class. For partial classes, that would imply examining every source file in the assembly! Being able to establish an invariant by examining two lines seems much nicer than having to examine an entire assembly.

With regard to initialization timing, I think having initializers run late but be able to use the object under construction is generally better than having them run early and be unable to use the object under construction (that's how VB.NET works, btw). The designers of C#, however, decided that having field initializers run before the base class was sufficiently important to give up the ability to have field initializers use the object under construction. In cases where the virtual method won't need to use parameters passed to the derived constructor, the effect of early initialization could be achieved like:
override void doSomething()
{
  if (!dejaVu)
    Initialize(); // Also sets dejaVu to true
  ...guts of method
}
Consequently, the only time that I can see early initialization would be semantically preferable to late would be if it made it possible to do something the above code couldn't. Thus, if early initialization is considered desirable, that would imply that it should be able to make use of passed parameter values.
Aug 28, 2014 at 9:04 AM
I already told my solution in another thread.
In my opinion, the primary constructor body is an unnecessary feature, at least before we have pattern matching, etc. People want constructor body, people want separate visibility, and people want blabla. My feeling is that people want a real good old constructor instead, so why invent a new confusing syntax for an old thing.

The primary constructor feature should really be designed together with pattern matching and other related features, not just a different way to write the same thing. It is getting back to the C++ days: there are several ways to write the same thing, let's debate which way is the one true way.
Aug 28, 2014 at 12:48 PM
Just a couple of quick comments on primary constructors
  • I think the curly brackets delimiting the primary constructor are important. It's no more soup than any other code block and identifies code that actually runs (and runs late) as opposed to fields (and setting them that runs early).
  • I think the early late discussion is a good one, but at present I like the new C# order. It avoids some trickery that VB used, and allows a clean explanation of the order in which things are done. Yes, this cuts out some scenarios - and I think this is the reason having primary constructor bodies prior to record classes makes sense.
Just my opinion,
Kathleen
Aug 28, 2014 at 6:45 PM
KathleenDollard wrote:
  • I think the curly brackets delimiting the primary constructor are important. It's no more soup than any other code block and identifies code that actually runs (and runs late) as opposed to fields (and setting them that runs early).
Would there be any problem with preceding the primary constructor body with a keyword like new to help make clear that's what it is?
  • I think the early late discussion is a good one, but at present I like the new C# order. It avoids some trickery that VB used, and allows a clean explanation of the order in which things are done. Yes, this cuts out some scenarios - and I think this is the reason having primary constructor bodies prior to record classes makes sense.
VB allows initialization expressions of later fields to use the values of other fields, a fact which I consider useful. What other "trickery" are you talking about? Otherwise, since the existing constructor bodies run after the primary constructor body, I'm unclear what purpose the primary constructor body would serve if it wasn't run "early".
Aug 28, 2014 at 7:55 PM
Edited Aug 28, 2014 at 8:42 PM
qrli wrote:
The primary constructor feature should really be designed together with pattern matching and other related features, not just a different way to write the same thing. It is getting back to the C++ days: there are several ways to write the same thing, let's debate which way is the one true way.
Primary constructors which run after the base class would be a redundant feature. Primary constructors which run before the base class would allow semantics which are not otherwise achievable.

Consider the design of an object which is supposed to count how many times an event gets raised. A base version of the class might count all events, but allow derived events to filter them. From a calling-code perspective, it would be cleanest to have the constructor be responsible for attaching the event [so the object can, from the moment it's constructed, maintain the invariant that if it exists and hasn't been disposed, the event is attached]. If the derived-class filter would needs to know what values were passed to the derived-class constructor, however, those values need to be made available to it before the base class attached the event.

If the framework were being designed from scratch, the cleanest way to handle such things would have been to have Object include a virtual ManageLifetime(LifetimeState) method which would be called (with different LifetimeState) when the class' outermost constructor finished execution or threw an exception, before letting code return to the constructor's caller. In that scenario, tasks that would require a constructor to either expose the object under construction or call virtual methods upon it could be deferred until ManageLifetime. No such feature exists, however, and the only way I can see to achieve such functionality with the existing Runtime would be to allow derived-class constructors to perform some parts of their initialization before there would be any possibility of the base class object attaching events.
Coordinator
Aug 29, 2014 at 1:27 AM
It is worth understanding that primary constructors are not intended to add new expressiveness. They are intended to be a shorthand for common patterns of code. The same is the case for many of the other features added this time around. They'll save you boilerplate and make your code shorter and clearer (or so I would argue), but they are not (with a few exceptions) for introducing new fundamental expressiveness.

This is deliberate. As Roslyn rolls out, there are plenty of new concepts to relate to. At the language level, we are keeping it "concept light". The ability to understand new features in terms of old ones is intentional and (in our view) beneficial.

As you can see from other posts, we are thinking about deeper new features, such as records, deconstruction and pattern matching. These will be pursued in a future round, where we have more of an appetite to open new fronts. I don't think those are in conflict with features we add today. Primary constructors, for instance, have very broad applicability. Records would target a more narrow scenario (e.g. they would be immutable), but would provide deeper benefits once you are in that scenario. We'll be very conscious about syntax and conceptual alignment, so that the features work together and, as much as possible, can be seen as extensions of each other.

But that's for later. In the version of C# we are building right now, we are celebrating our ability to finally address smaller and more syntactic issues - e.g. common cases of boilerplate overload. Primary constructors fall squarely in that bucket. I can hardly think of a class I'd write that wouldn't benefit significantly from primary constructors.

As a more general note, remember that C# is a language with a very broad user base. Some will be eager to live on the edge, and can't wait to see e.g. functional paradigms get more ingrained in the language. A large number of people really like where they are, and have no pressing desire to get inundated with new complexity. We have to evolve the language responsibly, and straddle often conflicting needs from the language as best we can, without our pants ripping, so to speak. We have to take the time to integrate new ideas cautiously and thoughtfully, in a way that fits well with the existing language and doesn't create fragmented subcultures like some other communities struggle with.

So please bear with us as we take our time to grow and do not always jump on new directions as quickly as you'd like. We are in it for the long haul and we have to keep the language relevant, productive and approachable for current and future users for many years to come.

Thanks,

Mads
Aug 29, 2014 at 5:28 AM
supercat wrote:
Primary constructors which run after the base class would be a redundant feature. Primary constructors which run before the base class would allow semantics which are not otherwise achievable.
That is a different feature which applies to all normal constructors. And it should be designed for normal constructors first, if it will be added at all.

But I agree with you that code block running before calling base constructor is a desired feature somehow, although the priority is not so high to me. IMO, the ideal syntax would be:
public Derived(string arg) {
Validate(arg);
base(arg); // compiler will give warning or error if it is not called
OtherInitialization();
}
Aug 29, 2014 at 5:55 AM
Edited Aug 29, 2014 at 5:57 AM
As for the primary constructor body syntax, I don't have a good idea either.
I'm slightly inclined to the scala choice. Because all the primary constructor thing have a style that the constructor is the class definition, or vise versa the class definition is the constructor. Another example is JavaScript's class. In this understanding, it makes sense to have constructor body directly inside the class braces, together with other properties, methods. And in practice, there should not be many methods in a class with primary constructor, so it will not reduce readability much. e.g.:
class Point(double x, double y) {
  if (double.IsNaN(x) || double.IsNaN(y))
    throw new ArgumentException(...);
  public double X { get; } = x;
  public double Y { get; } = y;
}
But I also agree that style will feel a bit strange to tradition C# users. We may would rather like a separate braced block, and better with prefix, e.g.:
new {
}

or

this {
}
It is also strange, because the constructor parameter declaration is not here but above. But we already have a similar case for property setter.

So, I don't like to see C# introduce it too fast. It may need more time.
Aug 29, 2014 at 7:10 PM
qrli wrote:
That is a different feature which applies to all normal constructors. And it should be designed for normal constructors first, if it will be added at all.
If a "primary constructor body" runs at the same point in the constructor sequence as an ordinary constructor, what difference would there be between including code in a primary constructor body, versus putting it in a method which is called from each constructor? The only difference I can see would be the ability to write to readonly variables without requiring that they be passed as ref or out parameters. Would late-executing "primary constructor bodies" serve some purpose that I'm not seeing? If not, why bother defining them at all?
But I agree with you that code block running before calling base constructor is a desired feature somehow, although the priority is not so high to me. IMO, the ideal syntax would be:
public Derived(string arg) {
Validate(arg);
base(arg); // compiler will give warning or error if it is not called
OtherInitialization();
}
The difficulty I see with that is that the constructor is effectively split into three parts: stuff which runs before the chaining call, then the chaining call, then stuff which runs after. Variables that were in scope before the base call should remain in scope afterward, but the only control structure which should be allowed to span the chained constructor call should be a try block which can be statically guaranteed to only exit via exception if an exception occurs in the try. I think such a constructor design would be great, if there were a good syntax for it, but implementing it would be enough work that I wouldn't expect it to ever come to fruition.

By contrast, from what I understand, having a primary constructor body run early would not be significantly easier nor harder than having it run late; it would basically be a matter of (1) placing the generated code before, rather than after, the chained call, and (2) making the scope restrictions which are applicable to field initializers also be applicable within the constructor body.
Aug 29, 2014 at 10:06 PM
qrli wrote:
I'm slightly inclined to the scala choice. Because all the primary constructor thing have a style that the constructor is the class definition, or vise versa the class definition is the constructor. Another example is JavaScript's class. In this understanding, it makes sense to have constructor body directly inside the class braces, together with other properties, methods. And in practice, there should not be many methods in a class with primary constructor, so it will not reduce readability much.
The biggest issue I see with regard to readability is maintaining a nice distinction between temporary variables (whose life time should end once construction completes) and fields. For example, if a class needs two immutably-sized arrays, both sized according to the larger of two passed-in parameters, it might want to do something like:
int newArraySize = size1 > size2 ? size1 : size2;
private readonly Thing[] firstackingStore = new Thing[newArraySize], secondBackingStore = new Thing[newArraySize];
To be useful, temporary variables would need to be in scope at the time the fields are created, but there's presently no syntax that would allow for something like that.
Coordinator
Sep 4, 2014 at 3:42 PM
To (finally) follow-up on the rename issues with nameof that @simonlbc posted, I've filed https://roslyn.codeplex.com/workitem/282.
Sep 4, 2014 at 11:50 PM
Pilchie wrote:
To (finally) follow-up on the rename issues with nameof that @simonlbc posted, I've filed https://roslyn.codeplex.com/workitem/282.
Thanks a lot!