c#属性可以没有GetMethod和SetMethod吗?
本文关键字:SetMethod GetMethod 属性 | 更新日期: 2023-09-27 18:02:45
浏览System.Linq. net核心源代码。表达式,我发现下面的代码位于这里:
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代码做出贡献,所以我试着看看哪些测试用例会覆盖这个
您可以在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'访问器
根据CLI规范,
CLS规则28:属性应遵循特定的命名模式。看到§I.10.4。CLS规则24中提到的SpecialName属性应为在适当的名称比较中忽略,并应遵循标识符规则。属性应该有一个getter方法,一个setter方法,或者两者。
在链接PDF的第52页。
这似乎说明其中一个必须在那里。
似乎开发人员决定以这种方式解释规范,并在面对无效数据时采取相应的行动。这似乎是一个相当合理的事情。
通过编写IL或随后编辑元数据,创建没有getter或setter的属性是可能的。. net加载器可能会继续加载它,即使它被认为是一个无效的属性。我在其他领域也见过这种事。
考虑到这一点,处理既没有getter也没有setter的属性的"不可能"情况的代码对我来说并不像是死代码。
经过一番研究,有一种方法可以实现这一点,通过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