更新:此问题已经过修改,以使其更加清晰。下面的答案似乎反映出这种方法效果很好。希望此问题可以帮助需要向现有媒体添加get
或set
的人。
今天遇到一个问题,我需要覆盖基类的get
- 仅包含get
和set
的属性。目前的共识似乎是这是不可能的,但我认为我找到了一种方法。
一般的想法是创建new
属性而不是直接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中覆盖。这是对的吗?
答案 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.