C# 属性 是否可以没有 GetMethod 和 SetMethod

Can a C# Property ever have no GetMethod and no SetMethod

浏览 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 都可以 return 为 null,正如此处似乎说明的那样?这是死代码吗? C# 编译器不允许 属性 没有 getter 和 setter,那么 PropertyInfo.

怎么可能呢?

我的动机是通过添加测试覆盖来为 OSS 代码做出贡献,所以我想看看哪些测试用例会覆盖这个

根据 CLI Specification

CLS Rule 28: Properties shall adhere to a specific naming pattern. See §I.10.4. The SpecialName attribute referred to in CLS rule 24 shall be ignored in appropriate name comparisons and shall adhere to identifier rules. A property shall have a getter method, a setter method, or both.

链接 PDF 的第 52 页。

这似乎是在说一个或另一个必须在那里。

看来开发人员决定以这种方式解释规范,并在面对无效数据时采取相应行动。似乎是一件很合理的事情。

通过编写 IL 或之后编辑元数据,创建一个没有 getter 或 setter 的 属性 是可能的。 .NET 加载器可能会继续加载它,即使它被认为是无效的 属性。我在其他领域也看到过这种事情。

考虑到这一点,处理 属性 的 "impossible" 情况的代码对我来说似乎不是死代码。

经过一些研究,有一种方法可以实现这一点,通过 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);

这显然是一个没有setter或getter没有IL

的奇怪方式

您可以在 IL 中创建一个没有访问器的 属性:

.class public C
{
  .property int32 Count() { } 
}

然后可以触发您提到的代码路径:

var prop = typeof(C).GetProperty("Count", BindingFlags.NonPublic | BindingFlags.Instance);

Expression.Property(null, prop);

此代码抛出:

ArgumentException: The property 'Int32 Count' has no 'get' or 'set' accessors