roslyn
roslyn copied to clipboard
Restrict some types in object initializer setters when not directly settable
This is a limited yet largely effective solution to #74331
Implementation details
When the property or field is not directly settable, we do not recommend the member as settable if any of the following is met:
- Type matches the types
Object,String,Enum,Array,Delegate,MulticastDelegate,IEnumerableandIEnumerator - Type is a generic substitution of
IEnumerable<T>orIEnumerator<T> - Type is a delegate, struct, pointer or function pointer
The above types have no settable members within an object initializer and cannot make use of a collection initializer. The only legal syntax they can have is X = { } which is a no-op setter, and since it's more of a trick than is being actually used, we do not offer the user the recommendation. They are still free to use the unrecommended members in the initializer, but only being able to "assign" { } as shown above.
We only filter Array itself because it does not support indexing. Array types with a concrete rank can be indexed within the initializer like so:
new()
{
// assume Array2D is int[,]
Array2D = { [0, 0] = value, [0, 1] = value1 },
}
Limitations
This is limited to just the known types as specified above. Other types that could be filtered out with the same properties, which would require traversing their members on-demand. This is a risky option because of the performance implications that could heavily affect the performance of the recommendation service which is intended to operate in real-time. It would be nice to have, but my personal view on solving that leans towards a cached value showing whether the type symbol can support object or collection initializers, being synchronized as the compilation is updated. Such a system would be very complicated and is not taken yet into consideration.
@CyrusNajmabadi ptal, let me know if the approach is appropriate
@CyrusNajmabadi ready for review with resolved comments
Thanks!