Roslyn: Parameter properties

Created on 10 Jun 2016  路  9Comments  路  Source: dotnet/roslyn

Any chance to have parameter properties in C# 7 as in Typescript?

Reference:
https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties

Area-Language Design Language-C# New Language Feature - Records

Most helpful comment

This example usage of Typescript better makes the point:
https://www.stevefenton.co.uk/2013/04/stop-manually-assigning-typescript-constructor-parameters/

In C# the same example

``` c#
public class Person {
public string firstName { get; set; }
private string lastName { get; set; } = "n.a.";

public Person (string firstName, string lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

}

shortens to this:

``` c#
public class Person {  
    public Person (public string firstName, private string lastName = "n.a.") { }
}

All 9 comments

This example usage of Typescript better makes the point:
https://www.stevefenton.co.uk/2013/04/stop-manually-assigning-typescript-constructor-parameters/

In C# the same example

``` c#
public class Person {
public string firstName { get; set; }
private string lastName { get; set; } = "n.a.";

public Person (string firstName, string lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

}

shortens to this:

``` c#
public class Person {  
    public Person (public string firstName, private string lastName = "n.a.") { }
}

That sort of shorthand is proposed for record types: #10154

public class Person(string firstName, string lastName = "n/a");

The one thing that I don't think has currently been resolved in that proposed spec is allowing for explicit member access modifiers on the parameters of the primary constructor.

@HaloFour thanks for the pointer!

In my understanding record types are very useful but only when creating _storage-only_ classes.

The parameter properties described above are more general I think:

  • they apply to classes in general and target any access modifier (public/private/etc.)
  • AFAIK they help/shorten a very frequent coding pattern

I would like having both, however if I have to choose one of them, I would prefer definitely parameter properties for their large applicability.

I never much cared for TypeScript's implementation of this feature because it makes it harder to see at a glance what the properties of your class are.

I think that problem would be compounded even further in C#, because in C# you can have multiple constructors (in TypeScript/JavaScript, you can only have a single constructor). It would be weird to have properties declared in one constructor that might be somewhere else in the code from the constructor you're looking currently.

@zpul

Perhaps. Records can contain class bodies complete with other methods, properties, etc. But they are proposed to automatically generate other record-specific boilerplate such as a deconstructor and possibly "withers". The syntax and functionality of your proposal is very similar so maybe the two could be considered side-by-side, whereas "property parameters" can be declared in normal constructors, but are promoted to "primary constructors" when the parameter list is moved to the type declaration:

public class Person {
    public Person(public string firstName, private string lastName = "n/a") { }
}

public class PersonRecord(public string firstName, private string lastName = "n/a");

Something that your proposal might have to take into consideration is that the C# naming guidelines stipulate that property names are PascalCase while parameter names are camelCase. The record proposal solves this through having a second identifier declared on the primary parameter, e.g.:

public class Person(string firstName FirstName, string lastName LastName);
...
var person = new Person(firstName: "John", lastName: "Smith");
Console.WriteLine($"Hello Mr. {person.LastName}!");

@MgSam

You're right, as with primary constructors it could only work if the type only had a single constructor. I also agree that it would be too easy to lose track of those members, and it's weird for something declared within the parameter list of a member to have a scope beyond that member.

@MgSam Very interesting point, however I think that it can be addressed in some way.
I agree with @HaloFour that it has to be limited in some way, either this should work on classes with one constructor or it should work only on one of them.
To address your comment the languange syntax can state that this constructor should be the first one and should appear at the very beginning of the class.

@HaloFour Thanks for the valuable feedback.
About CamelCasing I am usually not very strict on it however any idea such the one on record types is fine for me.

Not as the primary syntax for records, but I think this would be useful as an alternative.

Related: https://github.com/dotnet/roslyn/issues/10154#issuecomment-203577979

Whenever I use TypeScript and need to create a class I use this notation for brevity but it's actually a little weird.
public and protected make sense but private is really an odd ball because it exposes an implementation detail as part of a type's interface to simplify its implementation. The counter argument is that you should follow the principle of least privilege which which suggests the use of private. However, in that case it would be better to not declare the fact that the value is being captured into a property at all, and just do the wiring manually.

Issue moved to dotnet/csharplang #804 via ZenHub

Was this page helpful?
0 / 5 - 0 ratings