3

newサブクラスのメンバーを再定義して、より具体的な戻り値の型を利用できるようにするために使用することを検討しています。問題は、これは良い考えなのか、それともトラブルを求めているのかということです。

解決すべき問題は、いくつかの「ミラー化された」クラス階層があり、すべての階層層の型が別の階層の同じレベルを参照している場合です。説明が難しいので、以下に例を示します。

class A1 {}
class A2 : A1 {}
class A3 : A2 {}

abstract class B1
{
  protected A1 myA;

  A1 MyA { get { return myA; } }
}

abstract class B2 : B1
{
  new A2 MyA { get { return (A2)myA; } }
}

class B3 : B2
{
  new A3 MyA 
  { 
    get { return (A3)myA; } 
    set { myA = value; }
  }
}

他のすべてのレベルと同様に、抽象的な「レベル」1 ( A1/など) のみを処理するコードがあります。B1各「レベル」がタイプをできるだけ具体的に見るといいでしょう。現在、最上位レベルで型を定義し、呼び出しコードで常にダウンキャストしています。別の名前を使用して、ある「レベル」に別のメンバーを追加することがあります。これにより、より多くの冗長なメンバーが発生します。きれいにしたい。

(ジェネリックはここではオプションではありません。B2知らなければ役に立たないからですB3(そこに追加のインターフェースが必要になります)。また、多くのタイプがある場合(たとえば、C1/2/3、D1/2/3 ...)一般的な引数が多すぎます。技術的には機能しますが、非常に複雑になります。)

さらに、これらのクラスの一部をシリアライズし ( DataContractSerializer)、一部を NHibernate を使用してデータベースにマップします。

誰かがすでにこのようなことをしましたか?おすすめですか?同じ種類の問題を解決するための他のアプローチはありますか?

編集: キャストとプロパティの実装に関する議論のため、コードを少し変更しました。これは実際にはここでの質問ではありません。短い例を作成するために、できるだけ少ないコードを記述しようとしました。

4

2 に答える 2

2

私はあなたがそれを逆にやっていると思います...ダウンキャストは失敗するでしょう、あなたはアップキャストでそれを設計するべきです。の実装IEnumerableは、このパターンの最も一般的な例です。

最も派生した型は、最も派生した結果の作成を担当する必要があります。次に、基本型の仮想メソッドをオーバーライドして、アップキャスト(暗黙的である可能性があります)を介して最も派生した結果を返すことができます。

于 2010-07-08T08:53:41.357 に答える
2

私はそれをしません。

とにかくタイピングを節約するだけで、B3.MyA基本的にはパフォーマンスが低下しますreturn (A3)(A2)this.MyA;b3.MyA as A3必要な場合にのみ直接行うことができるのに、不要なキャストが多すぎます。

また、タイプのオブジェクトに初期化MyAするのを忘れた場合、それはタイプのオブジェクトなどであるため、キャストは失敗します。あなたは簡単に足で自分を撃つことができます。B3A3A1A2

編集:私が書いたことの要点は、それを行うためのタイプセーフな方法ではなく、決してそうなることはないということです。(編集したコードが示すように)それを行うリスクを最小限に抑えることができますが、その可能性はまだあります。私見では、そのような構成の利点は危険を正当化するものではありません。

Edit2Technically it would work, but it just gets very complicated. :一般的なアプローチに注意してください。

それほど複雑ではない私見。比較のために:

public abstract class B1<TA, TC> where TA: A1 where TC: A1
{
    public TA MyA { get; protected set; }
    public TC MyC { get; protected set; }
}

public abstract class B2<TA, TC> : B1<TA, TC> where TA : A2 where TC : A2
{
}

public class B3 : B2<A3, A3>
{
}

usingコードが少なくなり、安全性が向上します。入力が多すぎる場合は、いつでもステートメントを使用できることを覚えておいてください。

using ClassicB2 = MemberHiding.B2<MemberHiding.A3, MemberHiding.A3>;
ClassicB2 b3 = new B3();
于 2010-07-08T09:23:16.493 に答える