-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Lambdas omitting parameters #20
Comments
A wildcard character had been described in the C# Pattern Matching proposal which may be up for further discussion for C# 7.0. That character was How about also allowing skipping multiple arguments? void Foo(Func<string, int, bool, DateTime, decimal> func) { ... }
Foo(delegate { return 0m; }) // already valid C# 2.0+
Foo((*) => 0m); // shorthand for above
Foo((s, i, *) => 0m); // capture first two args, skip the rest If there are overloads which accept void Foo(Func<string, int, bool, DateTime, decimal> func) { ... }
void Foo(Func<string, int, bool, byte, DateTime, decimal> func) { ... }
Foo((s, i, *) => 0m); // calls the first Foo
Foo((s, i, *, *, *) => 0m); // calls the second Foo The one issue here, which also affects normal lambdas, is if there are overloads which accept a delegate with the same number of arguments but only differ by the type of those arguments. The only solution that I can think of there is to require specifying the type of the parameter in the lambda, but that makes the entire concept of catching multiple arguments feel weird. void Foo(Func<string, int, bool> func) { ... }
void Foo(Func<string, string, bool> func) { ... }
void Foo(Func<string, string, int, bool> func) { ... }
Foo((s, int *) => true); // calls first Foo
Foo((s, string *) => true); // calls second Foo
Foo((s, string *, *) => true); // calls third Foo, but ewww I think that a wildcard would be useful in a number of other scenarios as well, like the following: string s = ...;
if (int.TryParse(s, out *)) {
// Don't need the parsed value, no need to declare an extra variable
} |
The choice of the wildcard-symbol is not that important. I agree that void Foo(Func<string> func) { ... }
void Foo(Func<int, int, string> func) { ... }
void Foo(Func<int, int, bool, DateTime, string> func) { ... }
Foo(() => "0"); //->Calls first function
Foo(* => "0"); //->Compiler error, no function with 1 argument available
Foo((*) => "0"); //->Compiler error, no function with 1 argument available
Foo(** => "0"); //->Calls second function
Foo((**) => "0"); //->Calls second function
Foo((i, *) => i.ToString()); //->Calls second function
Foo((*, n) => n.ToString()); //->Calls second function
Foo((i, **) => i.ToString()); //->Calls second function
Foo((i, *, *) => i.ToString()); //->Compiler error, no function with 3 arguments available
Foo((i, *, **) => i.ToString()); //->Calls third function
Foo((i, *, *, *) => i.ToString()); //->Calls third function
Foo((i, *, *, **) => i.ToString()); //->Calls third function
Foo((i, *, *, *, *) => i.ToString()); //->Compiler error, no function with 5 arguments available
Foo((i, *, *, *, **) => i.ToString()); //->Compiler error, no function with 5+ arguments available The I actually have no problem with typing the wildcards. Of course the |
This should be thought of as a special case of allowing deconstruction in parameter position, which is something we will consider down the line. |
I attended a talk about C# 7 yesterday and saw the tuples and deconstruction features introducing the * wildcard to deconstruct a tuple where you only need certain values and lose the rest. This gave me the idea that it would be nice to also have a * wildcard for expressions, i.e. when dealing with events: public event EventHandler SomethingChanged;
private void DoStuff() {
SomethingChanged += (*, *) => {
// No need for sender and EventArgs
};
} |
We are now taking language feature discussion on https:/dotnet/csharplang for C# specific issues, https:/dotnet/vblang for VB-specific features, and https:/dotnet/csharplang for features that affect both languages. This proposal corresponds to dotnet/csharplang#111 |
I often have the situation of functions taking a lambda-expression as a parameter which take a handful of parameters themselves. Something like this:
Of course, delegates with many parameters are often an indicator of bad design, and should be avoided. But it's the same with fewer arguments.
A situation like the above get's quite painful if the lambda-body does not even need all those parameters (or is in extreme always returning the same, constant value). But still, the compiler requests me to find unique names for each of the parameters. This is a problem especially when renaming / adding variables "above" the anonymous function which do then interfere with the unused variables there.
Most of the time what I do today is something like this:
It also helps reading the code, because I can save a few characters (getting more 'good' code into a line) and make it obvious for readers which variables are important to me, making the code more understandable.
Of course this is somewhat limited, because my "placeholders" are really just ordinary names which must not reoccur. This might lead to something like
(_, __, foobar, ___) => ..
which starts to look ugly again.I would like it to have
_
(or just another special character, for backwards-compatibility) not usable for ordinary variable names and forbid it's actual usage inside the lambda-body. Therefore it could be used as a real placeholder, enabling something like this:or even this:
Does this sound like a useful thing to you?
The text was updated successfully, but these errors were encountered: