如何使用C#中的setter覆盖getter-only属性?

时间:2014-03-05 22:41:12

标签: c# override readonly setter getter

更新此问题已经过修改,以使其更加清晰。下面的答案似乎反映出这种方法效果很好。希望此问题可以帮助需要向现有媒体添加getset的人。


今天遇到一个问题,我需要覆盖基类的get - 仅包含getset的属性。目前的共识似乎是这是不可能的,但我认为我找到了一种方法。

一般的想法是创建new属性而不是直接override旧属性,然后我们创建一个overrideget方法的桥接方法打电话给新人。

场合

这是一些无法修改的任意预先存在的类型结构的代码。

public abstract class A
{
    public abstract int X { get; }
}
public class B : A
{
    public override int X { get { return 0; } }
}

问题

我们想编写这段代码,但不会编译。

public class C : B    // won't compile: X can't have a 'set' method
{
    private int _x;
    public override int X { get { return _x; } set { _x = value; } }
}

解决方案

我们编写了我们想要的代码,但是我们将属性声明为new而不是override,允许我们声明set方法。

public class D : C    // Same thing, but will compile because X is 'new'
{
    private int _x;
    public new virtual int X { get { return this._x; } set { this._x = value; } }  // also 'virtual', unless we want to 'sealed' it.

    //  Bridge method provides the override functionality:
    protected sealed override int XGetter { get { return this.X; } }  // 'sealed' because this bridge should always refer to the new 'get' method
}

额外桥接方法XGetter提供override。这使用中间层粘贴到基类结构:

public abstract class C : B  //abstract intermediate layer
{
    //  Override-and-seal the base property's getter.
    public sealed override int X { get { return this.XGetter; }  }

    //  Define the bridge property for the new class to override.
    protected abstract int XGetter { get; }
}

我认为D现在等同于继承自B的类,同时也能够在setter中覆盖。这是对的吗?

3 个答案:

答案 0 :(得分:1)

小心你的解决方案,因为它隐藏了A和B的原始意图。尽管如此,你的解决方案确实有效,即使在转换为基类时也是如此。

示例:

        D d = new D();
        d.X = 2;
        B b = d as B;

        Assert.AreEqual(2, b.X);

如果可以修改基类,我建议使用反射。

答案 1 :(得分:0)

<强>更新 以下是 INCORRECT

没有

public abstract class A
{
    public abstract int X { get; }

    public int GetXPlusOne()
    {
        return X + 1;
    }
}

您不会更改A.X的值。

var d = new D();
d.X = 10;

d.GetXPlusOne() == 1

答案 2 :(得分:0)

通过在您的示例中引入新属性XGetter,您已经使解决方案变得比它需要的更复杂。您可以引入相同的属性,然后反转哪个属性获取getter和setter。

public abstract class A
{
    public abstract int X { get; }
}
public class D : A
{
    private int _x;
    public sealed override int X { get { return XGetterSetter; } }
    public virtual int XGetterSetter { get { return this._x; } set { this._x = value; } }
}

在上面的示例中,D类中的代码与原始示例中的代码一样多。这样就不需要你的例子中的B类和C类。

从语义上讲,这个解决方案可能不一样。您必须设置XGetterSetter属性而不是X属性。 D的派生类也必须覆盖XGetterSetter而不是X.