在泛型类中隐藏非泛型基类属性或方法的标准模式是什么?
我有2个解决方案实际上是做同样但不同的方法。解决方案之一使用更多内存,因为基类和派生类引用相同的对象,而解决方案2因为转换而慢。(或者我错了?)
基础课程:
public class MyDataBase {}
public class MyDataDerived : MyDataBase {}
public class BaseFoo
{
private readonly MyDataBase _data;
public MyDataBase Data { get { return _data; } }
public BaseFoo(MyDataBase data) {
_data = data;
}
}
解决方案1:
public class GenericFooWithHiding<T> : BaseFoo where T : MyDataBase
{
private readonly T _data;
public GenericFooWithHiding(T data) : base(data) { _data = data; }
public new T Data { get { return _data; } }
}
解决方案2:
public class GenericFooWithCasting<T> : BaseFoo where T : MyDataBase
{
public GenericFooWithCasting(T data) : base(data) {}
public new T Data { get { return base.Data as T; } }
}
答案 0 :(得分:1)
如果我从这两个中选择的话,我会采用第二种(强制转换)方法:将相同的数据存储在多个地方是非常有保证的方法,使它们不同步。如果表现很重要的话,我会发挥铸造成本(不太可能显着) - 测量和验证。
旁注:我会尝试避免使用new
属性,因为根据您拥有的变量类型,它会引起混淆。使基类'Data
属性受到保护可能是特定样本的潜在解决方案。
答案 1 :(得分:1)
解决方案3
反转BaseFoo
和GenericFoo<T>
之间的继承关系,因此泛型的使用变得很重要,根本不需要隐藏。
public class MyDataBase {
}
public class MyDataDerived: MyDataBase {
}
public class GenericFoo<T> where T: MyDataBase {
public GenericFoo(T data=default(T)) {
}
public T Data {
get {
return _data;
}
}
protected readonly T _data;
}
public class DerivedFoo: GenericFoo<MyDataDerived> {
public DerivedFoo(MyDataDerived data=default(MyDataDerived))
: base(data) {
}
}
public class BaseFoo: GenericFoo<MyDataBase> {
public BaseFoo(MyDataBase data=default(MyDataBase))
: base(data) {
}
}
答案 2 :(得分:0)
我认为您无法更改BaseFoo
类型,因为否则您可以首先将其设为通用。
我不会使用new
来更改返回类型,因为这可能会让人感到困惑。例如:此代码段中data
的类型是什么?
GenericFoo<MyDataDerived> foo = new GenericFoo<MyDataDerived>(new MyDataDerived());
var data = ((BaseFoo)foo).Data;
是MyDataBase
(致电BaseFoo
)。但是,如果BaseFoo
中的虚拟属性在GenericFoo
中被覆盖,将被调用?:
public class BaseFoo
{
public virtual MyDataBase MoreData
{
get
{
return _data;
}
}
}
public class GenericFoo<T> : BaseFoo where T : MyDataBase
{
public override MyDataBase MoreData
{
get
{
return _someOtherData;
}
}
}
// which property is called?
var data = ((BaseFoo)foo).MoreData;
这次通话转到GenericFoo
。由于这通常是预期的行为,我建议不要使用new
。
我会在GenericFoo
中实现一个方法,以避免使用new
(我会使用强制转换):
public class GenericFoo<T> : BaseFoo
where T : MyDataBase
{
public T GetData()
{
return (T)base.Data;
}
}