0

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

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

3 回答 3

2

如果要从这两种方法中进行选择,我会采用第二种(强制转换)方法:将相同的数据存储在多个地方几乎可以保证使它们不同步。因此,如果性能很重要,我会考虑铸造成本(不太可能是重要的) - 衡量和验证。

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

于 2013-03-05T01:15:04.340 回答
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) {
    }
}
于 2013-03-05T01:42:58.927 回答
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;
    }
}
于 2013-03-05T03:17:57.617 回答