繁体   English   中英

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

[英]How to override a getter-only property with a setter in C#?

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


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

一般的想法是创建一个new属性而不是直接override旧的,然后我们创建一个桥接方法, override调用新的来override旧的get方法。

情况

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

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 中覆盖。 这样对吗?

请注意您的解决方案,因为它隐藏了 A 和 B 的原始意图。话虽如此,您的解决方案确实有效,即使在转换为基类时也是如此。

例子:

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

Assert.AreEqual(2, b.X);

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

UPDATE:下列哪项不正确

不。

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

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

您不会更改AX的值。

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

d.GetXPlusOne() == 1

通过在您的示例中引入新属性 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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM