0

ジェネリック クラスで非ジェネリックな基本クラスのプロパティまたはメソッドを非表示にするための標準パターンは何ですか?

私は実際には同じですが異なるアプローチを行う2つの解決策を持っています。解決策 1 は、基本クラスと派生クラスが同じオブジェクトを参照するため、より多くのメモリを使用します。また、解決策 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

これらの 2 つから選択した場合、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 に答える