TL;DR;
在 C# 中禁止使用可设置属性覆盖或实现 get-only 属性。
部分正确。使用可设置属性实现仅获取属性是完全有效的 - 但使用可设置属性覆盖仅获取属性是无效的。
长版:
当我尝试编译您的代码时,我遇到了两个编译错误(在 VS 2017 中,如果这很重要的话)
错误 CS0106 修饰符“抽象”对此项无效
错误 CS0106 修饰符“public”对此项目无效
当从接口的属性中删除public abstract时,代码编译得很好(删除了抽象类,因为它在这里无关紧要):
public class Example : IExample
{
public int Property { get; set; }
}
public interface IExample
{
int Property { get; }
}
但是,当尝试使用抽象类并使用 get/set 属性覆盖 get only 属性时,出现以下编译错误:
错误 CS0546“Example.Property.set”:无法覆盖,因为“ExampleBase.Property”没有可覆盖的 set 访问器
对于以下代码(删除了接口,私有集同样的错误):
public class Example : ExampleBase
{
public override int Property { get; set; }
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
这实际上是一个很好的方式来展示 C# 中覆盖和实现之间的区别:
接口是一种契约。它强制实现类型将其成员作为其公共 API 的一部分(除了显式实现)。所以当实现一个带有 get-only 属性的接口时,你可以给这个属性添加一个 setter,因为只要它有 getter,契约仍然是被履行的。
但是,基类不是契约。如果强制继承类具有完全相同的成员签名,但允许继承类覆盖虚拟成员(因此相同的方法或属性将在两个类中实现不同)。事实上,派生类是它的基类的(特定)类型。
通常,如果您想在基类中为 get-only 属性添加 setter,则必须使用关键字 new 隐藏它,但这对抽象成员没有帮助 - 必须重写抽象成员在派生类中 - 由于我们没有属性重载,因此您必须添加一个方法来设置 get-only 属性的值,并显式实现它:
public class Example : ExampleBase
{
private int _property;
public override int Property { get { return _property; } }
public void SetProperty(int property)
{
_property = property;
}
}
public abstract class ExampleBase
{
public abstract int Property { get; }
}
为了完整起见 - 如果基本属性不是抽象的,您将如何使用 new 关键字:
public class Example : ExampleBase
{
public new int Property { get; set; }
}
public class ExampleBase
{
public virtual int Property { get; }
}