6

重複の可能性:
C# - 「タイプを切り替える」ためのこれよりも優れた代替手段はありますか?

古典を考えてみましょう:

class Widget { }
class RedWidget : Widget { }
class BlueWidget : Widget { }

ほとんどの場合、私の UI では、すべてをWidget同じように扱うことができます。ただし、小さな違いがあり、それを通過する必要がありifますswitch

可能なアプローチ:

列挙型インジケーター- コンストラクターによって設定

enum WidgetVariety { Red, Blue }

class Widget {
    public WidgetVariety Variety { get; protected set; }
}

class RedWidget : Widget {
    public RedWidget() {
        Variety = Red;
    }
}

// Likewise for BlueWidget...

switch (mywidget.Variety) {
case WidgetVariety.Red:
    // Red specific GUI stuff

case WidgetVariety.Blue:
    // Blue specific GUI stuff
}

使用するis

Widget w = ...;
if (w is RedWidget) {
    (RedWidget)w ...
}
else if (w is BlueWidget) {
    (BlueWidget)w ...
}

私がこれに頼った理由は次のとおりです。1) ほとんどのコードはすでにこのように書かれていますが、かなり醜いです。2) コードの 90% は同一です。基本的に、GridView の 1 つの列だけをタイプに応じて異なる方法で処理する必要があります。

どちらをお勧めしますか?(または、誰かがより良い解決策を持っていますか?)


編集私はおそらく訪問者パターンに推奨されることを知っていますが、この場合、まばらで小さな違いのために単純に複雑に思えます。

編集2 したがって、私が整理するのに苦労していた特定の違いの1つは、2つのタイプ間で異なるこの列です。あるケースでは、bool値を取得し、それをグリッド セルに割り当てます。それ以外の場合は、文字列値を取得します。

この場合、次のように定義できることは明らかだと思います。

public object virtual GetColumn4Data();

public override GetColumn4Data() { return m_boolval; }

public override GetColumn4Data() { return m_mystring; }

を使用しているため、これは最初は間違っていると感じましたobject。しかし、それ私がセルで割り当てているプロパティのタイプなので、もちろんこれは理にかなっています!

今日はオフィスにいる時間が長すぎるようです...

4

3 に答える 3

9

別の可能性があります。仮想ディスパッチを使用する:

class Widget
{
    public virtual void GuiStuff() { }
} 
class RedWidget : Widget
{
    public override void GuiStuff()
    {
        //... red-specific GUI stuff
        base.GuiStuff();
    }
} 
class BlueWidget : Widget
{
    public override void GuiStuff()
    {
        //... blue-specific GUI stuff
        base.GuiStuff();
    }
} 
于 2012-04-11T22:49:12.443 に答える
5

サブタイプのポリモーフィズムが最善の解決策です。この種のチェックを回避することが、OO が作成された主な理由の 1 つです。

WidgetメソッドDoSomething()(おそらく抽象)があり、それRedWidgetBlueWidgetオーバーライドする可能性があります。

Martin Fowler のReplace Conditional with Polymorphismも参照してください。

見た: オブジェクトのタイプに応じて異なる動作を選択する条件があります。

リファクタリング: 条件の各レッグをサブクラスのオーバーライド メソッドに移動します。元のメソッドを抽象化します。

于 2012-04-11T22:49:40.063 に答える
0

編集#2の質問については、ジェネリッククラスを使用してサブクラス間でタイプを変えることができますが、デザインによっては機能する場合と機能しない場合があります。おそらく、他の厳しい設計上の決定につながるでしょう。

大まかな例:

internal abstract class BaseClass
{
   protected object mValue; // could also be defined as a T in BaseClass<T>

   public object GetColumn4Data { get { return mValue; } }
}

// this is a group of classes with varying type
internal abstract class BaseClass<T> : BaseClass
{
   public T GetTypedColumn4Data 
   {
      get { return (T)mValue; } 
      set { mValue = value; }
   }
}

// these are not really necessary if you don't plan to extend them further
// in that case, you would mark BaseClass<T> sealed instead of abstract
internal sealed class BoolSubClass : BaseClass<bool>
{
   // no override necessary so far
}

internal sealed class StringSubClass : BaseClass<string>
{
   // no override necessary so far
}

ただし、一部のプロパティまたはメソッドでさまざまな戻り値の型を持つ単一の参照型を実際に取得することはできないことに注意してください。BaseClass参照はせいぜい一般的な型 ( など) を返しますobject

于 2012-04-12T00:42:12.890 に答える