【发布时间】:2019-09-03 16:56:55
【问题描述】:
在 C# 中,覆盖自动属性并仅提供一个访问器会通过 PropertyInfo“丢失”另一个访问器进行反射,即使它是在基类中定义的。
乍一看可能很奇怪,但仔细分析后似乎是reasonable。
但是,将 override 更改为 sealed override 也会更改此行为并允许获取所有访问者:
using System.Reflection;
using NUnit.Framework;
[TestFixture]
public class PropertySealedOverrideReflectionTests
{
public class Base
{
public virtual object Override { get; set; }
public virtual object SealedOverride { get; set; }
}
public class Derived : Base
{
public override object Override { set => base.Override = value; }
public sealed override object SealedOverride { set => base.Override = value; }
}
[Test]
public void Override()
{
PropertyInfo overrideProperty = typeof(Derived).GetProperty(nameof(Derived.Override));
// ---
// getter from base class is "invisible" here
// ---
Assert.False(overrideProperty.CanRead);
Assert.Null(overrideProperty.GetMethod);
}
[Test]
public void SealedOverride()
{
PropertyInfo sealedOverrideProperty = typeof(Derived).GetProperty(nameof(Derived.SealedOverride));
// ---
// after changing to "sealed override" getter is in place
// ---
Assert.True(sealedOverrideProperty.CanRead);
Assert.NotNull(sealedOverrideProperty.GetMethod);
}
}
在提供的场景中,编译器的类型会发生什么变化以执行sealed override?这种行为的原因是什么?
【问题讨论】:
-
当名称相同时,您是否看到相同的行为?意思是基类中的
Override,子类中的sealed override Override?在这种情况下,sealed应该做的就是防止您在另一个子类中覆盖,就像 Derived 的子类将无法覆盖 SealedOverride -
抱歉没有收到您的问题。我以这种方式命名属性只是为了便于说明。
-
C# 编译器必须确保密封整个属性覆盖的唯一方法是密封
get和set访问器。然后要实现这一点,它必须实际覆盖get访问器,即使您没有在覆盖中编写任何 getter。当然,C# 编译器只会在它自己“发明”的访问器中调用基本实现。通过反射,会显示该 get 访问器的存在。 -
@detective 谢谢,但从 C# 语言的角度来看,
sealed override应该做什么很清楚,我所指的问题和行为是通过反射从基类获取属性获取器的可访问性,请参阅单元测试从问题。
标签: c# .net reflection system.reflection