11

在基类中,我有这个属性:

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

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

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

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

4

5 回答 5

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

像这样更改基类属性,您正在尝试覆盖不存在的 set 方法

于 2009-08-04T12:27:55.770 回答
5

在您的第二个代码块中,您正在创建一个公共 set 方法,但声明中的“覆盖”一词使编译器在基类中寻找具有相同签名的方法。由于它找不到该方法,因此不允许您创建集合。

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

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

///<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")
}

否则,将集合声明为子类中的单独方法:

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

public void SetText(string value)
{
    differentText = value;
}
于 2009-08-04T12:36:41.620 回答
3

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

在基类中:

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

在派生类中:

new public string Text 
{
    get { return text; }
    set { text = value; }
}
于 2009-08-04T13:32:17.643 回答
2

这是一个问题,因为您正在破坏封装。您不能覆盖某些内容并使其更易于访问,这会将有关封装的所有内容都抛诸脑后。

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

没有办法完全按照您的尝试去做。您必须在基类中创建一个 setter,或者使用不同的方法来设置新值。

于 2009-08-04T12:41:31.777 回答
2

您可以从基类中隐藏该属性:

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

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

于 2009-08-04T13:00:38.953 回答