Can we add inline expressions for method params?
(string emailAddress = emailAddress?.ToLower()) //email address always lower if a value is passed
Optional parameters today cannot do that because they must be known at compile time. This isn't an arbitrary constraint. The compiler must know the default value at compile time because the compiler emits calls to the method by simply taking the default value of the parameter and using that as the parameter's value.
A related feature request might be a new syntax for optional parameters whose values are determined at run time, but that's fairly problematic in terms of how they are exposed outside of the assembly. All of that said, this works just as well:
public void Foo(string emailAddress)
{
emailAddress = emailAddress?.ToLower();
}
Your suggestion just moves the expression from the method body into the parameter.
You can write everything in for loops also. That isn't the point. It simplifies the code while maintaining legibility. I don't get how it is problematic at all for exposure because everyone calling in will only know it as a string.
Why would you reference a feature request without giving a link to it? Please include the reference in your comment so others can see.
It's not a default value. It's an inline expression which simultaneously proposes a new non-lambda syntax for expressions.
It simplifies the code while maintaining legibility.
I disagree. Like I said, you just moved code from one place to another when it would work verbatim in the method body. Meanwhile, there is a lot to consider here. How would overriding a method that has one of these parameters work? What if it's abstract or on an interface?
There is another way to look at this. Could it be about declaring a method contract that a string parameter value has to be in lowercase?
https://github.com/dotnet/roslyn/issues/119
public void Sample(string emailAddress)
requires emailAddress == emailAddress?.ToLower()
{
//...
}
Of course this is not exactly same because the original sample _guarantees_ lower case while mine fails if it's not lowercase. So the proposal could be:
public void Sample(string emailAddress)
prepares emailAddress = emailAddress?.ToLower()
{
//...
}
So it's a like a "pre-action" instead of a precondition and piggy-backs a planned feature.
Different way of thinking about it also
public void Test(string emailAddress, bool? dumbo) :
emailAddress?.ToLower() ?? "string is empty",
dumbo ?? false
{
return emailAddress;
}
Or,
public void Test(string emailAddress) {
emailAddress = emailAddress?.ToLower() ?? "string is empty";
}
Having thought about this suggestion, I've now removed my down-vote and have applied it to @alrz's comment instead. To explain this, it's a case of how complex the code is to follow in your head. With @alrz's example, it's a case of:
public void Test(string emailAddress) // emailAddress has a value
{
emailAddress = emailAddress?.ToLower() ?? "string is empty"; // email address now has
// a new value...
}
The re-assignment of emailAddress
adds to the cognitive complexity of the code. Whenever a value of a variable changes, I have to hold that fact in my head whilst reading the code. 10 lines later, that can become a problem; if I'm faced with a 500 line method, with dozens of ever-changing variables, it becomes a nightmare.
However, I don't think that @brandonseydel's solution is right either. Whilst the original example changes the value of emailAddress
in the same line as declaring it (and thus is easier to follow mentally), it's still uses the "mutate variables" approach. The solution I'd take (which the language already supports, and which can be enforced with analyzers), is to declare a new variable to take the mutated value:
public void Test(string rawEmailAddress)
{
var correctedEmailAddress = rawEmailAddress.ToLower();
...
}
(I deliberately also removed the ?
as I don't like defensive code; I prefer the TDD approach of having a test fail is I ended up passing a null
into Test
.)
(And at some point, we might get both support for the let
statement and readonly
parameters, and then even the analyzers can be retired...)
I don't get why people are just putting stuff that can already be done. Everyone knows it can be done that way. The point is to enhance the capabilities of the language not to post asshole responses. If you don't like it then explain why. Nobody needs your primitive examples of how it can be done a different way. _cough cough_ @alrz @vcsjones
@brandonseydel
I don't get why people are just putting stuff that can already be done.
Because comparing proposed language feature against what can be done in the existing language is very useful when evaluating how useful a feature is.
The point is to enhance the capabilities of the language
That's not the only metric that's important. Things like simplicity of language and not being surprising (string emailAddress = null
does one thing, but string emailAddress = emailAddress?.ToLower()
does something very different?) are important too.
not to post asshole responses
Please don't call people names, it doesn't help anybody.
If you don't like it then explain why.
- That's not how it works. If you do like it, you have to make the case why this would be a useful feature, since features start at -100 points.
- I think that @vcsjones did explain why he didn't like it. And @alrz didn't say he didn't like it.
Nobody needs your primitive examples of how it can be done a different way.
I disagree, if you don't evaluate alternatives (both potential and existing), you're not going to find the best choice.
We are now taking language feature discussion in other repositories:
Features that are under active design or development, or which are "championed" by someone on the language design team, have already been moved either as issues or as checked-in design documents. For example, the proposal in this repo "Proposal: Partial interface implementation a.k.a. Traits" (issue 16139 and a few other issues that request the same thing) are now tracked by the language team at issue 52 in https://github.com/dotnet/csharplang/issues, and there is a draft spec at https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md and further discussion at issue 288 in https://github.com/dotnet/csharplang/issues. Prototyping of the compiler portion of language features is still tracked here; see, for example, https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation and issue 17952.
In order to facilitate that transition, we have started closing language design discussions from the roslyn repo with a note briefly explaining why. When we are aware of an existing discussion for the feature already in the new repo, we are adding a link to that. But we're not adding new issues to the new repos for existing discussions in this repo that the language design team does not currently envision taking on. Our intent is to eventually close the language design issues in the Roslyn repo and encourage discussion in one of the new repos instead.
Our intent is not to shut down discussion on language design - you can still continue discussion on the closed issues if you want - but rather we would like to encourage people to move discussion to where we are more likely to be paying attention (the new repo), or to abandon discussions that are no longer of interest to you.
If you happen to notice that one of the closed issues has a relevant issue in the new repo, and we have not added a link to the new issue, we would appreciate you providing a link from the old to the new discussion. That way people who are still interested in the discussion can start paying attention to the new issue.
Also, we'd welcome any ideas you might have on how we could better manage the transition. Comments and discussion about closing and/or moving issues should be directed to https://github.com/dotnet/roslyn/issues/18002. Comments and discussion about this issue can take place here or on an issue in the relevant repo.
I am not moving this particular issue because I don't have confidence that the LDM would likely consider doing this.
Most helpful comment
@brandonseydel
Because comparing proposed language feature against what can be done in the existing language is very useful when evaluating how useful a feature is.
That's not the only metric that's important. Things like simplicity of language and not being surprising (
string emailAddress = null
does one thing, butstring emailAddress = emailAddress?.ToLower()
does something very different?) are important too.Please don't call people names, it doesn't help anybody.
I disagree, if you don't evaluate alternatives (both potential and existing), you're not going to find the best choice.