为什么我不能为重写属性添加set访问器?

时间:2009-08-04 12:26:17

标签: c# inheritance properties accessor

在基类中我有这个属性:

public virtual string Text 
{
    get { return text; }
}

我想覆盖它并返回不同的文本,但我也希望能够设置文本,所以我这样做了:

public override string Text
{
    get { return differentText; }
    set { differentText = value; }
}

然而,这不起作用。我在set下得到一个红色波浪形,说我无法覆盖,因为它没有设置访问器。为什么这是个问题?我该怎么办?

5 个答案:

答案 0 :(得分:5)

public virtual string Text 
{
    get { return text; }
    protected set {}
}

像这样改变基类属性,你试图覆盖不存在的set方法

答案 1 :(得分:5)

在第二个代码块中,您正在创建一个公共集方法,但声明中的“override”一词使编译器在基类中查找具有相同签名的方法。由于找不到该方法,因此无法创建您的设置。

正如ArsenMkrt所说,您可以将基本声明更改为包含受保护的集合。这将允许您覆盖它,但由于您仍然无法更改签名,因此您无法在子类中将此方法提升为public,因此您发布的代码仍然无效。

相反,您需要向基类添加一个公共虚拟集方法,该方法不执行任何操作(如果您尝试调用它,甚至会抛出异常),但这违背了类的用户所期望的如果你这样做的行为是这样的(我不会推荐它)确保它有很好的文档记录,用户不能错过它:

///<summary>
///Get the Text value of the object
///NOTE: Setting the value is not supported by this class but may be supported by child classes
///</summary>
public virtual string Text 
{
    get { return text; }
    set { }
}

//using the class

BaseClass.Text = "Wibble";
if (BaseClass.Text == "Wibble")
{
    //Won't get here (unless the default value is "Wibble")
}

否则将该set声明为子类中的单独方法:

public override string Text
{
    get { return differentText; }
}

public void SetText(string value)
{
    differentText = value;
}

答案 2 :(得分:3)

使用子类型时,您希望显示更多功能。这听起来像你不想覆盖,你想要阴影。只需使用new关键字隐藏可读/可写属性下的只读Text属性。

在基类中:

protected string text;
public string Text 
{
    get { return text; }
}

在派生类中:

new public string Text 
{
    get { return text; }
    set { text = value; }
}

答案 3 :(得分:2)

这是一个问题,因为你打破了封装。你不能覆盖某些东西并使它更易于访问,这会把关于封装的一切都抛到窗外。

这是规则,它也适用于你的情况,尽管你实际上暴露了一些不是原始值的东西。

无法完全按照您的尝试行事。您必须在基类中创建一个setter,或者使用另一种设置新值的方法。

答案 4 :(得分:2)

您可以从基类隐藏属性:

public new string Text
{
    get { return differentText; }
    set { differentText = value; }
}

但在这种情况下,只有在通过此类型的变量操作对象时才使用该属性,而不是基类型