171

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

オブジェクトのタイプを使いたい場合switch、これを行う最善の方法は何ですか?

コードスニペット

private int GetNodeType(NodeDTO node)
{
    switch (node.GetType())
    { 
        case typeof(CasusNodeDTO):
            return 1;
        case typeof(BucketNodeDTO):
            return 3;
        case typeof(BranchNodeDTO):
            return 0;
        case typeof(LeafNodeDTO):
            return 2;
        default:
            return -1;
    }
}

これがうまくいかないことはわかっていますが、どうすればこれを解決できるのだろうと思っていました。この場合、if/else発言は適切ですか?

.ToString()または、スイッチを使用してタイプに追加しますか?

4

10 に答える 10

156

独自のユーザー定義型をオンにしたいので、これは問題を直接解決しませんが、組み込み型のみをオンにしたい他の人の利益のために、TypeCode列挙を使用できます。

switch (Type.GetTypeCode(node.GetType()))
{
    case TypeCode.Decimal:
        // Handle Decimal
        break;

    case TypeCode.Int32:
        // Handle Int32
        break;
     ...
}
于 2011-02-04T19:41:58.830 に答える
92

オブジェクトのタイプが本当に必要な場合は、 を使用します。ただし、私はそれを絶対に避けます。はるかにうまくいくでしょswitch.ToString()IDictionary<Type, int>

于 2009-04-02T09:10:32.327 に答える
30

私は同じ問題に直面しており、この投稿に出くわしました。これが IDictionary アプローチの意味ですか。

Dictionary<Type, int> typeDict = new Dictionary<Type, int>
{
    {typeof(int),0},
    {typeof(string),1},
    {typeof(MyClass),2}
};

void Foo(object o)
{
    switch (typeDict[o.GetType()])
    {
        case 0:
            Print("I'm a number.");
            break;
        case 1:
            Print("I'm a text.");
            break;
        case 2:
            Print("I'm classy.");
            break;
        default:
            break;
    }
}

もしそうなら、辞書の数字とケースステートメントを一致させるのが好きだとは言えません。

これは理想的ですが、辞書参照はそれを殺します:

void FantasyFoo(object o)
{
    switch (typeDict[o.GetType()])
    {
        case typeDict[typeof(int)]:
            Print("I'm a number.");
            break;
        case typeDict[typeof(string)]:
            Print("I'm a text.");
            break;
        case typeDict[typeof(MyClass)]:
            Print("I'm classy.");
            break;
        default:
            break;
    }
}

私が見落とした別の実装はありますか?

于 2009-12-02T20:17:25.687 に答える
29

if ステートメントを使用するだけです。この場合:

Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ... 

これを行う別の方法は次のとおりです。

if (node is CasusNodeDTO)
{
}
else ...

最初の例は正確な型のみに当てはまり、後者は継承もチェックします。

于 2009-04-02T09:12:16.970 に答える
16

あなたはこれを行うことができます:

function void PrintType(Type t) {
 var t = true;
 new Dictionary<Type, Action>{
   {typeof(bool), () => Console.WriteLine("bool")},
   {typeof(int),  () => Console.WriteLine("int")}
 }[t.GetType()]();
}

それは明確で簡単です。辞書をどこかにキャッシュするよりも少し遅くなります..しかし、多くのコードでは、これはとにかく問題になりません..

于 2010-08-04T00:52:52.080 に答える
13

あなたはこれを行うことができます:

if (node is CasusNodeDTO)
{
    ...
}
else if (node is BucketNodeDTO)
{
    ...
}
...

それはよりエレガントですが、ここでの他のいくつかの回答ほど効率的ではない可能性があります.

于 2009-04-02T09:12:33.913 に答える
7

1 つの方法は、純粋な仮想 GetNodeType() メソッドを NodeDTO に追加し、子孫でそれをオーバーライドして、各子孫が実際の型を返すようにすることです。

于 2009-04-02T09:13:11.027 に答える
5

switch文で何をしているかにもよりますが、正解はポリモーフィズムです。インターフェイス/基本クラスに仮想関数を配置し、ノード タイプごとにオーバーライドするだけです。

于 2009-04-02T14:08:20.270 に答える
0

私は実際にここで答えとして与えられたアプローチを好みます: これよりも「タイプを切り替える」ためのより良い代替手段はありますか?

ただし、C# などのオブジェクト指向言語で型比較メソッドを実装しないことについては、十分な議論があります。別の方法として、継承を使用して必要な機能を拡張および追加することもできます。

この点については、次の著者のブログのコメントで説明されています

これは、同様の状況で私のアプローチを変更した非常に興味深い点であり、これが他の人に役立つことを願っています.

敬具、ウェイン

于 2012-07-06T20:11:21.133 に答える