Discard parameters in method definition #6954
Replies: 7 comments 26 replies
-
@copygirl Can't you overload these methods? so it would look something like this: void Tab(string name, Action<Entity, History?, Entity?> contentMethod)
{
// ...
}
void Tab(string name, Action<Entity?> contentMethod)
=> Tab(name, (_, _, selected) => contentMethod(selected)); Independently to your request I feel like repeating yourself over and over by discarding isn't as pleasant experience as opposed to define precisely what you need once. Just to clarify I understand what you're asking but looking at methods that their parameters was discarded is odd and I'm not sure how it's going to work with overload resolution but it seems to have things backwards in a way, instead of defining what you need as in my example with this proposal certain methods wouldn't have usable parameters similar to anonymous methods and lambada expressions only there it's local and make sense. |
Beta Was this translation helpful? Give feedback.
-
I think this can be useful when implementing interfaces or overriding virtual methods. |
Beta Was this translation helpful? Give feedback.
-
IMO it's just not worth it. Names are cheap, and ultimately the compiler would have to invent one anyway as it's unlikely that much tooling was designed to support unnamed parameters. Given that parameter names are a part of the contract of a method (and changing them can cause source breaking changes), whether or not you're using them, it seems to me that you should still name them. |
Beta Was this translation helpful? Give feedback.
-
This topic came up when discards were first discussed and it puzzled me why it was skipped even then. At the time, I felt the compelling use case was event handlers. An event handler has to fulfil a method signature contract, but all too often (it wouldn't surprise me if it weren't in the overwhelming majority of cases), those parameters are not used in the handler's code: private void OnMonitoredFileChange(object sender, FileSystemEventArgs e)
{
// code that never uses sender or e
} I disagree that "names are cheap". Naming things is hard; this is a very well established fact of programming. In addition, names convey meaning, often confusingly, but they convey meaning. So expressing it as: private void OnMonitoredFileChange(object _, FileSystemEventArgs _)
{
// ...
} instantly clarifies the meaning of those parameters: they are needed for a contract, but they aren't used. I think it a nonsense to use the -100 points argument here. That applied to the concept of discards themselves. They were felt compelling enough to implement them: to allow their use in assignments, discards, patterns, for lambda parameters ... everywhere that you'd have a need for a discard at times, with the sole exception of method parameters. It's like having a small stone in your boot. It's an irritation, but is it irritating enough to justify stopping, unlacing the boot, discarding the stone and relacing the boot? Probably not. Not being able to use discards for method parameters will just remain one of those annoying functionality inconsistencies that all apps, even compilers, accrue over time. |
Beta Was this translation helpful? Give feedback.
-
See csharplang/meetings/2019/LDM-2019-10-28.md Lines 30 to 34 in 6ea8ab1 |
Beta Was this translation helpful? Give feedback.
-
I wrote a post and came to post it here, but found this discussion. I'll copy here what I would have posted. I think this feature would be as beneficial as any other discard feature. There is a feature to discard out parameters etc and also code hints for them. But there is no feature the other way around. If a function or method has unused parameters, it will generate an IDE0060 remove unused parameter (parameter
Suggestion: Allow discarding parameters by naming them as underscore to denote intentionally unused parameters in at least virtual, override and interface implementation signatures and also event delegates if possible. If someone is using underscore intentionally as a parameter name, use of such variable should produce an error (possibly breaking change). I would guess that any existing cases are for discarding purposes just as described above. |
Beta Was this translation helpful? Give feedback.
-
I understand that there's good reason for keeping this the same - backwards compatibility. That said, since C# is no longer fully opposed to breaking changes, my personal preference and an option to consider might be treating anything named Preventing the use of discard assignmentvoid SomeMethod(bool _)
{
// ...
_ = SomeOtherMethod_ReturnTypeIsNotBool(); // CS0029
SomeOtherMethod_ReturnTypeIsNotBool(); // CA1806
// ...
} Assuming that "False positive" use of discard assignmentLet's say we're subscribing to an event with a sender and some EventArgs. We don't care about the sender. void OnEvent(object _, EventArgs e) Per the original specification here, SummaryIn short, I feel like it would be better to treat anything named |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Proposal
My proposal is for the language to allow the use the discard syntax in method definitions. That is, naming multiple parameters
_
.This is already possible when defining lambdas, so I feel this is just an extension of that.
When a single parameter is named
_
, the behavior should stay the same as previous C# versions, and allow referring to the parameter by name.When multiple discard parameters with name
_
are used, an error should be generated if one were to attempt to refer to them.Use-case 1
I have written a sort of DSL for my game engine which uses a source generator to analyze methods and their signature, and generates some additional code that actually defines and executes a query which will interact with a C library. I have chosen unused parameters to represent terms in this query which never hold any meaningful value.
Here is one such method:
This will query every entity in the game that has a
Mesh
set, but does not yet have aMeshHandle
, which is created when uploading the mesh to the graphics card, which is exactly what this method will do. It is a simplified example, but this will occur many times in my code.Now as you can see I have two parameters in this method that I don't actually end up using, hence the naming
_1
and_2
.With this change in place, I would be allowed to write the following, instead:
Use-case 2
In some cases, a method may take a delegate argument such as
Action<A, B, C>
(or a properdelegate
type with named parameters). A method passed to this other method might not need to make use of multiple of the given parameters, and as such it could use the discard syntax for them.Beta Was this translation helpful? Give feedback.
All reactions