Proposal: allow open types in nameof #2547
-
(Created from #4827) Currently to use
I propose that the exact same syntax as class GenericClass<T>
{
public string X { get; }
}
class GenericClass<T1, T2>
{
public string Y { get; }
} These expressions are currently valid, and would stay valid: nameof(GenericClass<int>)
nameof(GenericClass<int>.X)
nameof(GenericClass<int, byte>)
nameof(GenericClass<int, byte>.Y) These expressions would become valid, and would have the same respective results: nameof(GenericClass<>)
nameof(GenericClass<>.X)
nameof(GenericClass<,>)
nameof(GenericClass<,>.Y) Using the terminology in https://github.com/ljw1004/csharpspec, it may be that all we need to do in grammar terms is to expand |
Beta Was this translation helpful? Give feedback.
Replies: 34 comments
-
Should |
Beta Was this translation helpful? Give feedback.
-
Absolutely not. The main use case for I'm not normally one to throw a ton of emoji reactions at things, but I'm still in disbelief that C# hasn't shipped with this yet. Also, I'd like an analyzer to warn on |
Beta Was this translation helpful? Give feedback.
-
A |
Beta Was this translation helpful? Give feedback.
-
@alrz It should return a similar thing to |
Beta Was this translation helpful? Give feedback.
-
@alrz I don't disagree, but the important part, what This is borne out. Try The only reason to specify class GenericClass<T> { }
class GenericClass<T, TOther> { }
nameof(GenericClass<>): GenericClass
nameof(GenericClass<,>): GenericClass class GenericClass<T> { }
class GenericClassNewName<T, TOther> { }
// Rename refactor was able to track that we care about the name of the unary class in this scenario
nameof(GenericClass<>): GenericClass
// Rename refactor was able to track that we care about the name of the binary class in this scenario
nameof(GenericClassNewName<,>): GenericClassNewName |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Yeah you got a point. 😄 |
Beta Was this translation helpful? Give feedback.
-
That could be the case. Not sure about nameof, but dotnet/roslyn#10972 certainly works for me. |
Beta Was this translation helpful? Give feedback.
-
@alrz If you wanted the CLR type name, |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Yes, only it's not a constant. |
Beta Was this translation helpful? Give feedback.
-
That's right, but it could be if Roslyn starts recognizing |
Beta Was this translation helpful? Give feedback.
-
As per the original proposal, I'm suggesting that using the open type should produce the same results as a constructed type. While I can see there being uses for the generic form, we can't change the results of |
Beta Was this translation helpful? Give feedback.
-
However, I'm pretty comfortable with using constructed types, as I'm already used to it. |
Beta Was this translation helpful? Give feedback.
-
I think using discards would make the implementation easier as there would be no syntax changes. nameof(GenericClass<_>)
nameof(GenericClass<_>.X)
nameof(GenericClass<_,_>)
nameof(GenericClass<_,_>.Y) |
Beta Was this translation helpful? Give feedback.
-
@alrz Shouldn't this |
Beta Was this translation helpful? Give feedback.
-
@eyalsk It could, but it does not resolve any ambiguity because there is none. EDIT: The parser does seem to be totally capable of producing syntax nodes for missing identifiers. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Sorry, @jskeet didn't outline a language grammar. If you don't have any idea either, I'll let the issue sit. |
Beta Was this translation helpful? Give feedback.
-
To be clear, the problem is that |
Beta Was this translation helpful? Give feedback.
-
@gafter I am not familiar with language grammar, but it seems obvious to me that |
Beta Was this translation helpful? Give feedback.
-
@jnm2 I agree, that would work. But we treat it as an invocation expression so we do not break backward compatibility. |
Beta Was this translation helpful? Give feedback.
-
I want this badly enough that I'll get up to speed on language grammar to help get this through, but I doubt I'm the most valuable person in this thread for that purpose. :') What if the hybrid expression, the argument to
At a source level, any currently-valid argument to |
Beta Was this translation helpful? Give feedback.
-
https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#nameof-expressions Okay, so the operand to
But that would be a problem for info_of expressions because of back-compat. Perhaps it's better they stay separate from named_entity. (See, I doubt I'm the most valuable person in this thread...) |
Beta Was this translation helpful? Give feedback.
-
To get back to basics here, this is what we currently have (spec#nameof-expressions): named_entity
: simple_name
| named_entity_target '.' identifier type_argument_list?
; What if there was a version of |
Beta Was this translation helpful? Give feedback.
-
@gafter How is this? nameof_expression
: 'nameof' '(' named_entity_open ')'
: 'nameof' '(' named_entity_closed ')' // For back-compat
;
named_entity_open
: simple_name
| named_entity_target_open '.' identifier generic_dimension_specifier?
;
named_entity_target_open
: 'this'
| 'base'
| named_entity_open // Gotta be open all the way: TypeA<int>.TypeB<> doesn't make sense
| predefined_type
| qualified_alias_member
;
named_entity_closed // For back-compat
: simple_name
| named_entity_target_closed '.' identifier type_argument_list?
;
named_entity_target_closed // For back-compat
: 'this'
| 'base'
| named_entity_closed // Gotta be closed all the way: TypeA<>.TypeB<int> doesn't make sense
| predefined_type
| qualified_alias_member
; |
Beta Was this translation helpful? Give feedback.
-
A simple way to handle this from the grammar would be to just change:
into
With normative text to specify that the latter are only legal in the respective locations in typeof/nameof. -- This grammar would be essentially mimic what we are already doing in the C# parser today. i.e we support "generic-dimension-specifiers" everywhere, we just report errors if you use them in inappropriate locations. We do this to make parsing simple and to reduce the number of node types we need. i.e. we don't need multiple type of type-argument-lists. But we then go and enforce that you're not using the wrong type of node in the wrong location. |
Beta Was this translation helpful? Give feedback.
-
The spec grammar is ambiguous, because it requires semantic context to distinguish a |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi @gafter Do you need any more guesswork from me or do you have a handle on it? :) |
Beta Was this translation helpful? Give feedback.
-
Absolutely yes please to this feature and please include VB. |
Beta Was this translation helpful? Give feedback.
-
@jskeet Would you please port this to csharplang? |
Beta Was this translation helpful? Give feedback.
-
@jnm2: Done - follow the link above :) |
Beta Was this translation helpful? Give feedback.
-
Championed proposal being scheduled for LDM soon: #8480 |
Beta Was this translation helpful? Give feedback.
Championed proposal being scheduled for LDM soon: #8480