将非泛型基类属性隐藏在泛型类中

时间:2013-03-05 00:44:33

标签: c# generics inheritance return-type

在泛型类中隐藏非泛型基类属性或方法的标准模式是什么?

我有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; } }
}

3 个答案:

答案 0 :(得分:1)

如果我从这两个中选择的话,我会采用第二种(强制转换)方法:将相同的数据存储在多个地方是非常有保证的方法,使它们不同步。如果表现很重要的话,我会发挥铸造成本(不太可能显着) - 测量和验证。

旁注:我会尝试避免使用new属性,因为根据您拥有的变量类型,它会引起混淆。使基类'Data属性受到保护可能是特定样本的潜在解决方案。

答案 1 :(得分:1)

解决方案3

反转BaseFooGenericFoo<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;
    }
}