Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C# Design Notes for Nov 15, 2016 #16674

Closed
MadsTorgersen opened this issue Jan 21, 2017 · 3 comments
Closed

C# Design Notes for Nov 15, 2016 #16674

MadsTorgersen opened this issue Jan 21, 2017 · 3 comments

Comments

@MadsTorgersen
Copy link
Contributor

C# Language Design Notes, Nov 15, 2016

Quote of the day: "Bad people don't get good features!"

Agenda

  • Tuple name warnings
  • "Discards"

Tuple name warnings

There are two kinds of warnings on the table regarding names in tuples:

  1. A warning on tuple literals only, if the literal uses an element name that isn't in the target type
  2. A warning on all expressions of tuple type if an element name in the expression is used for a different element in the target type

The first warning helps get the names right when writing a tuple literal, and while maintaining it. It is already in the product:

(int x, int y) t = (a: 1, b: 2); // Oops, forgot to update tuple literal? Names a and b would be lost

The second warning would help guard against bugs due to reordering of tuple elements:

(string firstName, string lastName) GetName();

(string lastName, string firstName) name = GetName(); // Oops, forgot to swap the element names in name?

This warning is currently not in the product. We would like it to be, but don't have the runway to implement it.

In the future it could be added as an analyzer, or as a compiler warning protected by warning waves (#1580).

"Discards"

We got great feedback on "wildcards" at the MVP Summit, including changing its name to the term "discards", which is spreading in industry.

We are also encouraged to use _ as the discard character instead of *. It works better visually, and is what many other languages already use.

There is a small matter of _ already being a valid identifier. In order for it to coexist as a discard with existing valid uses we need to use a few tricks. Here are the essential rules:

  1. A standalone _ when no _ is defined in scope is a discard
  2. A "designator" var _ or T _ in deconstruction, pattern matching and out vars is a discard

Discards are like unassigned variables, and do not have a value. They can only occur in contexts where they are assigned to.

Examples:

M(out _, out var _, out int _); // three out variable discards
(_, var _, int _) = GetCoordinates(); // deconstruction into discards
if (x is var _ && y is int _) { ... } // discards in patterns

One use case is to silence warnings when dropping Tasks from async methods:

_ = FooAsync();

We also want to allow discards as lambda parameters (_, _) => 0, but don't expect that to make it in C# 7.0. Today _ is allowed as an ordinary identifier; the rule would be that it would become a discard if there's more than one.

We can also consider allowing top-level discards in foreach loops:

foreach (_ in e) { ... } // I don't care about the values

But that does not seem too important, especially since you can use var _ to the same effect.

In general, whenever use of standalone _ as a discard is precluded, either by syntactic restrictions or by _ being declared in the scope, var _ is often a fine substitute with the same meaning. However, if the declared _ is a parameter or local, there are situations where you are out of luck:

public override void M(int _) // declaring _ to signal that this override doesn't care about it
{
	_ = TryFoo();     // Error: cannot assign bool result to int variable _
	var _ = TryFoo(); // Error: cannot declare local _ when one is already in scope
}

These situations are always local to a member, so it is relatively easy to rewrite them, e.g. to rename the incoming parameter. We could consider accommodating them in the future: the error for a local redeclaration of _ when one is already in scope could be changed to allowing it, but consider the second declaration a discard. This may be too subtle, and not useful enough, but it is worth considering post C# 7.0.

@vbcodec
Copy link

vbcodec commented Jan 21, 2017

Design notes everyday :)
Please also bring latest Sprint Summary, it also stuck somewhere in the pipeline

@DavidArno
Copy link

DavidArno commented Jan 21, 2017

We also want to allow discards as lambda parameters (_, _) => 0, but don't expect that to make it in C# 7.0

Discards are a brilliant new feature, and even what's to be offered with C# 7 will be useful. Regarding the extension to that functionality to cover lambda parameters, it really would be good if this were allowed in method declarations too. This would be of use when, eg defining event handler methods, where the event parameters aren't used.

@jcouv
Copy link
Member

jcouv commented Jul 29, 2017

LDM notes for Nov 15 2016 are available at https://github.com/dotnet/csharplang/blob/master/meetings/2016/LDM-2016-11-15.md
I'll close the present issue. Thanks

@jcouv jcouv closed this as completed Jul 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants