-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
C# 9 "init-only" properties; unable to detect IsExternalInit via reflection API - and a pragmatic proposal #43088
Comments
Note: an advantage of |
Additional workaround idea: the compiler could emit a |
Try this: using System;
public class Foo
{
public int A { get; init; }
}
class Program
{
static void Main(string[] args)
{
foreach (var m in typeof(Foo).GetMethod("set_A").ReturnParameter.GetRequiredCustomModifiers())
Console.WriteLine(m);
}
} Prints "System.Runtime.CompilerServices.IsExternalInit" |
@jkotas well ... fair enough; TIL - thanks; apparently we can detect it, and all is well with the world; not obvious, but it works |
Agree that it is not obvious. modreqs/modopts can be only attached to a type in the method signature. So the way to attach them to the method is to attach them to the method return type in the method signature instead. |
makes sense now, thanks; have this detection working in a library branch now - minimal changes (protobuf-net now correctly handles unattributed positional |
(note: if this is possible and I've just overlooked it; please do tell me!)
The current "init-only" implementation is nice in some ways, as existing libraries (e.g. serialization etc) will "just work", since
SetValue
(and the equivalent in IL) just work; however, one weakness is that it seems impossible for libraries that want to respect the "init-only"-ness to actually detect it; if we consider, for example:or
this gets compiled as:
i.e. with the
modreq
on the method.The problem with this is that no existing reflection API allows you to detect this feature.
PropertyInfo
hasGetOptionalCustomModifiers()
/GetRequiredCustomModifiers()
, butMethodInfo
does not, and since themodreq
is on the setter, it is not inspectable. All we can detect is attributes, i.e.[CompilerGenerated]
.This makes it impossible for the type to be understood properly be reflection-based code.
I wonder if there are some pragmatic things that could be done here; for example, adding an attribute as well; obvious contenders might be
[ReadOnly(true)]
on the property (or perhaps type, in therecord
case?). There is a small problem here; the regular caller might also have added this attribute, since the following is valid:but maybe something similar? Maybe a new attribute that we can check for, that is declared in tandem with
IsExternalInit
?An alternative would be to add some new APIs; either:
PropertyInfo.IsExternalInit
(very specific; also, naming is hard)MethodInfo.GetOptionalCustomModifiers()
/MethodInfo.GetRequiredCustomModifiers()
(larger change, more reusable)The downside of the "new API" approach is that it doesn't work on older TFMs that have hacked themselves an
IsExternalInit
The text was updated successfully, but these errors were encountered: