-
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
Support for method parameter names in nameof() #373
Comments
Why is Or |
How would you resolve multiple method overloads? It's not ambiguous in the use-site, but when you rename either of parameters in the method declaration, it's not clear which one |
@alrz |
That seems like a lot of new syntax, however, the attributes in the example above are on the method itself. I think it would be nice to just bring them into the scope, e.g. [Attribute(nameof(parameter))]
void M(object parameter, [Attribute(nameof(parameter))] object p) { } |
I agree. |
@jnm2 you could a typo of me there unfortunately. i meant to write it like nameof(GetChildrenOf.siteId). I'd rather stay in line with the ordinary nameof syntax |
@alrz I would probably resolve it like this given we have the following methods
Which would resolve in options to use nameof like this:
I agree that merely bringing them into scope would already be a significant improvement for most use cases - but rather than having to bypass data through attributes, one might just go all the way from the start then. |
Quoting @perholje #771 (comment) |
cc @jcouv Note that the class Path
{
[return: NotNullIfNotNull(nameof(path))] // This fails to compile, needs to be "path" instead
public static string? GetFileName(string? path);
} In fact, the LDM notes inadvertently specified code that won't compile due to this 🙂 - https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-05-15.md#nullness-dependencies-between-inputs-and-outputs |
Retracted. You will always get the same IL no matter what this binds to (since the I think tha'ts actually totally acceptable. I don't think the language should be restricted from changing here just because it might end up causing a downstream IDE tooling change. IMO, the new behavior would be entirely intuitive and would be in line with what people want anyways. So i change my position to 👍 on this. |
Just putting my 2 cents in as well that this would be useful, especially with the addition of the |
@jaredpar brought up a scenario could break depending on how we implement this: class A : System.Attribute
{
public A(int i, string s) { }
}
class C
{
const int item1 = 123;
int item2;
[A(item1, nameof(item2))]
void M(int item1, int item2) { }
} If we don't specify/implement it carefully, item1 will start binding to the parameter and the code will no longer compile. So one suggestion is that we could attempt to bind the attribute argument using basically the "binder we already have today", and if the lookup fails, attempt to bind again using a binder that knows about the method parameters. Apologies if I'm mangling the terms here. Alternatively we could decide no, the user needs to change their code to say |
Is it possible to specify it'll only bind to a parameter of the method an attribute is applied on if it's inside a |
@RikkiGibson That sure is an interesting edge case he came up with. In that scenario i would however say that the feature should just raise a compile error if it can't distinguish between symbols. After all you are free to pick and choose argument names without major impacts on your code, so utilizing the benefits of forwarding argument names to attributes would still exist even if you have that case.
|
@taori that's just one naming convention, and not even the default VS one. |
@yaakov-h Yeah - sure. Well i guess the language team will wrap their head around this one since there seems to be quite some interest in implementing this feature to ensure compilation safety for the nullness safety feature. |
Yes. That would be my preference. |
Funny thing, I thought of this exact option to be the final disambiguator, if nothing else will do. I even had thought out that the user experience when in the context |
We probably would want to do this either before or at the same time as #287 |
The compiler could detect if there is a already a private member with same name as the param name and enforce the user to either prefix its methodname => nameof(Method1.Param1) or rename the private member variable. (e. g. adding an underscore). |
Why would it matter if there was a field in scope with the same name as the parameter? |
Could affect refactoring if you wanted to rename that parameter or field. This is something that tooling could handle without language/compiler changes, though, by asking for disambiguation. |
Yeah. Not a lang issue afaict. |
The refactoring issue is already kind of a problem with method overloads that have the same name so tooling improvements in this area would be beneficial and could address both those issues. |
How about |
@batzen what if I have a field named |
Sorry, meant |
With the new |
FYI, added a speclet link to OP: https://github.com/dotnet/csharplang/blob/main/proposals/extended-nameof-scope.md |
Feature was merged for VS 17.3p2 |
Update (jcouv): speclet (https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/extended-nameof-scope.md)
it would be fairly amazing if nameof also worked for MethodName arguments.
I think i've talked about this 1-2 years ago and some aspnet member also chimed in and mentioned how this could be useful for magic EntityFramework where the appropriate name must be passed too for connection strings to work.
So essentially i would love it if, instead of strings, i could be typing this:
or this
Update (jcouv):
This proposal (in its most likely and straightforward design) would affect scoping rules and thus would introduce a breaking change. It is worth considering whether this breaking change is severe. Here's an example to illustrate the problem:
Some alternatives for LDM to consider:
nameof
nameof
to reference parameters with the method name as a qualifier[Attr(nameof(M.p)] void M(int p) { }
LDM history:
The text was updated successfully, but these errors were encountered: