-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Champion "Lambda discard parameters" (VS 16.8, .NET 5) #111
Comments
Please, please, please could this apply to methods too? Sometimes, the parameters must be there, but just aren't used. By way of example, this Unit type has to have both R# and public static bool operator ==(Unit u1, Unit u2) => true;
public static bool operator !=(Unit u1, Unit u2) => false; Being able to write those with discards to reassure those checks that the parameters must be there, but aren't used, would clean up such code nicely: public static bool operator ==(Unit _, Unit _) => true;
public static bool operator !=(Unit _, Unit _) => false; |
@DavidArno I believe the .NET Framework design guidelines have always been to use the names |
Oh, I didn't know that. I'll give that a try to see if it makes the compiler happier. Would still like to be able to use discards though. |
this proposal also permit in nested lambda expression Enumerable.Range(0, 3)
.SelectMany(_ => Enumerable.Range(0, 3)
.SelectMany(_ => Enumerable.Range(0, 3))); // i don't need parameters in nested |
@acple Possibly not, unless we also do something like dotnet/roslyn#15793 at the same time. |
@gafter Thank you. in my opinion, lambda parameter shadowing is a bit dangerous but, discarded parameters are safe to overcover. so that should support only with discarded parameters. is this shadowing issue? or discarding issue? |
@acple This is a shadowing issue. When there is only one lambda parameter named |
@gafter okay I understand. desire the identifier definition rules will be relaxed partially... thanks for the information! 😄 |
there should also be a compiler warning/error when using an items.ForEach(_ => Console.WriteLine(_)); |
Unfortunately, that would be a breaking change. An analyzer could be added to this affect though. |
I think use of a single |
I disagree. If I was going to use the parameter in the lambda body, then I'd use eg I appreciate that's personal opinion though. |
@DavidArno Exactly, it is personal opinion. My rationale is that I'd like to not have to specify a parameter at all, so until I can do |
I disagree that it is a personal opinion, since it is a common convention in functional languages that Thankfully it is quite simple to give it a proper name. |
Oh, the irony. |
From discussion today in LDM, we're going to keep the feature narrow for now (only support it for lambdas and anonymous methods as initially proposed). |
Can I ask why doing this for all methods is more complicated? |
@YairHalberstadt It's not a question of implementation cost, but trade-off between language complexity and benefit to users. Methods are part of an API (they can be invoked, whereas lambdas can only be converted to delegates, so the parameters names are never accessible to callers). |
Aren't they available through reflection? I rely on that in a library. |
@jcouv Can local functions be included? They are often converted to delegates. |
You raise a good point re methods that I hadn't thought of. Consider the following code example, public interface I
{
public void M(int a, int b);
}
public class C : I
{
public void M(int _, int _) {}
}
public static class P
{
private static void Main()
{
I i = new C();
C c = new C();
i.M(a:1, b:1);
c.M(_:1, _:1);
}
} In But if I'm a developer working in a team that insists on named parameters (not sure if such a team exists, but thinking worst case here), then that line My motivation for wanting discards in methods (and operators, though I'm just lumping them in with methods here) is for situations such as when defining event handlers, operators and the like. In these situations, I have to specify the parameters to meet the contract. But if I then don't use those parameters, the But maybe this is the wrong solution to the problem. If a method must have a parameter to meet the contract, but that parameter isn't used, the |
@DavidArno I think in the case you present, that should likely be a compiler error since But, I think explicit implementations maybe could allow discarded parameters since those methods are only callable through the interface signature. A potential (but perhaps unlikely) addition to that would be to also allow it in method overrides provided that the overriding class is less visible than the base class? Idk, it's obviously quite a complicated scenario. |
I agree, the better approach would seem to have the analyzers not generate diagnostics for unused parameters that are required to meet the contract, such as for implicit implementation of an interface member or for overloaded operators, etc. In general I'm a little squeamish about extending |
Including local functions sounds perfect. Even private methods have their reflection concerns. |
Will this also work for LINQ (as LINQ gets compiles down to lambdas)? For those of us that use LINQ for more than just querying an enumerating this would be an absolute godsend. It would reduce the calls for an extension to the LINQ grammar. For example, I'm just working on a new IO monad: static SIO<Runtime, ConsoleKeyInfo> ShowError(Error err) =>
from _1 in setColor(Red)
from _2 in writeLine(err.Message)
from _3 in writeLine()
from _4 in writeLine(StackTrace(err))
from _5 in setColor(White)
from k in readKey
select k; I would prefer to do this: static SIO<Runtime, ConsoleKeyInfo> ShowError(Error err) =>
do setColor(Red)
do writeLine(err.Message)
do writeLine()
do writeLine(StackTrace(err))
do setColor(White)
from k in readKey
select k; But would be fine with just this (as a stopgap until the day that LINQ gets some much needed love): static SIO<Runtime, ConsoleKeyInfo> ShowError(Error err) =>
from _ in setColor(Red)
from _ in writeLine(err.Message)
from _ in writeLine()
from _ in writeLine(StackTrace(err))
from _ in setColor(White)
from k in readKey
select k; |
I asked this question on Twitter, but figured I should bring it over here Question, for those insane folks who use Is there a different character you can use that would have otherwise been invalid pre C# 9? |
@ChaseFlorell No, it is not a breaking change. This feature only kicks in when at least two parameters are discarded. |
@jcouv do we have an existing issue covering multiple discards for methods, or multiple discards for locals? |
@CyrusNajmabadi Tracked by #2180 |
Thanks! |
Examples:
(_, _) => 1
,(int _, string _) => 1
,void local(int _, int _) ...
See
The text was updated successfully, but these errors were encountered: