Quote of the day: "Bad people don't get good features!"
There are two kinds of warnings on the table regarding names in tuples:
The first warning helps get the names right when writing a tuple literal, and while maintaining it. It is already in the product:
``` c#
(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:
``` c#
(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).
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:
_
when no _
is defined in scope is a discardvar _
or T _
in deconstruction, pattern matching and out vars is a discardDiscards are like unassigned variables, and do not have a value. They can only occur in contexts where they are assigned to.
Examples:
``` c#
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:
``` c#
_ = 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:
``` c#
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:
``` c#
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.
Design notes everyday :)
Please also bring latest Sprint Summary, it also stuck somewhere in the pipeline
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.
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
Most helpful comment
Design notes everyday :)
Please also bring latest Sprint Summary, it also stuck somewhere in the pipeline