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