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代码做出贡献,所以我试着看看哪些测试用例会覆盖这个

c#属性可以没有GetMethod和SetMethod吗?

您可以在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

就没有setter或getter显然是一种奇怪的方式