浏览System.Linq.Expressions的.NET核心源代码,我发现以下代码位于here:
MethodInfo mi = property.GetGetMethod(true);
if (mi == null)
{
mi = property.GetSetMethod(true);
if (mi == null)
{
throw Error.PropertyDoesNotHaveAccessor(property, nameof(property));
}
}
GetGetMethod
和 GetSetMethod
是否有任何方法可以返回null,这似乎可以解释为什么?这是死代码吗?
C#编译器不允许属性没有getter而没有setter,所以PropertyInfo
如何实现。
我的动机是通过添加测试覆盖率来为OSS代码做出贡献,所以我试图看看哪些测试用例会覆盖这个
答案 0 :(得分:4)
您可以在IL中创建一个没有访问者的属性:
.class public C
{
.property int32 Count() { }
}
然后可以触发您提到的代码路径:
var prop = typeof(C).GetProperty("Count", BindingFlags.NonPublic | BindingFlags.Instance);
Expression.Property(null, prop);
此代码抛出:
ArgumentException:属性'Int32 Count'没有'get'或'set'访问者
答案 1 :(得分:2)
CLS规则28:属性应遵循特定的命名模式。看到 §I.10.4。 CLS规则24中引用的SpecialName属性应为 在适当的名称比较中忽略,并应遵守标识符 规则。属性应具有getter方法,setter方法或 两者。
这是链接PDF的第52页。
这似乎说一个或那个必须在那里。
开发人员似乎决定以这种方式解释规范,并在面对无效数据时采取相应行动。看起来很合理。
通过编写IL或之后编辑元数据,可以创建一个没有getter或setter的属性。并且.NET加载器可能会继续加载它,即使它被认为是无效的属性。我见过这种事情发生在其他领域。
考虑到这一点,处理具有getter和setter的属性的“不可能”情况的代码对我来说似乎不是死代码。
答案 2 :(得分:2)
经过一些研究,有一种方法可以通过System.Reflection.Emit
实现这一目标AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.Run);
ModuleBuilder module = assembly.DefineDynamicModule("Module");
TypeBuilder type = module.DefineType("Type");
PropertyBuilder property = type.DefineProperty("Property", PropertyAttributes.None, typeof(void), new Type[0]);
Type createdType = type.CreateType();
PropertyInfo createdProperty = createdType.GetTypeInfo().DeclaredProperties.First();
Console.WriteLine(createdProperty.GetGetMethod(true) == null);
Console.WriteLine(createdProperty.GetSetMethod(true) == null);
这显然是一种没有IL
的没有setter或getter的奇怪方法