根据定义,private 成员不可覆盖。
如果您希望 setter 可被覆盖,您可以将其标记为 protected 而不是 private。
private abstract class InheritanceTest
{
public virtual object Property
{
get { return null; }
protected set { }
}
public class Child : InheritanceTest
{
public override object Property
{
get { return null; }
protected set { base.Property = null; }
}
}
}
要更具体地回答您关于为什么的问题:
了解当您的 C# 代码编译为 IL 代码时,实际上 1 个属性最终会产生 3 个东西。
-
Property 属性本身。
- 一个名为
get_Property() 的方法,它是getter。
- 一个方法名为
set_Property(),它是setter。
在您的代码中,您告诉 .NET “我想要一个 virtual 属性。然后它将访问级别级联到 getter 和 setter 方法。实际上,在 IL 代码中,属性不指定 virtual at全部。
对于 C# 代码:
public virtual object Property { get; set; }
生成的IL代码为:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method public hidebysig newslot specialname virtual
instance object set_Property() cil managed
{ ... }
请注意,public 和 virtual 关键字适用于 getter 和 setter 方法,但不适用于属性本身。
现在,通过将 C# 代码更改为:
public virtual object Property { get; private set; }
你已经告诉 .NET 你希望你的 getter 和 setter 方法是虚拟的......然而,然后它运行到private set,并且访问级别覆盖 public 和 virtual 访问级别,用于 setter 方法。所以,生成的IL代码就变成了:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method private hidebysig newslot specialname
instance object set_Property() cil managed
{ ... }
请注意,现在 set_Property() 是 private,不再是 virtual。在 .NET 中实际上不可能有 private virtual,因为它没有意义......这就像试图说“没有其他类可以看到这个......但是派生类可以覆盖这个东西,他们看不到或访问”这是没有意义的。派生类不能覆盖他们甚至看不到的东西。
protected 关键字在这种情况下是合适的替代品,因为它告诉 .NET “只有我自己和派生类可以看到或访问这个,派生类可以覆盖这个属性。”
所以我猜“简短”的答案应该是“因为 .NET 中的事情不能是 private 和 virtual,所以编译器会采用你给它的更受限制的访问级别。
另外,IMO 的错误信息非常正确。
“Program.InheritanceTest.Child.Property.set”:无法覆盖继承的成员“Program.InheritanceTest.Property.set”,因为它没有标记为虚拟、抽象或覆盖
请注意,它说的是'Program.InheritanceTest.Property.set',所以末尾的“.set”指的是最终的set_Property() 方法,而不是Property 属性。并且set_Property() 方法仅标记为private,因为.NET 编译器看到了这一点,并出于上述原因从该方法中删除了virtual。我想有一个编译器警告或者说“虚拟将被'set'忽略”是有道理的。
希望这更有意义...