2012-03-10 2 views
2

私は "マリオ"ビデオゲームを作成しようとしています。交差オブジェクトを取得するために、教師は私たちに例証デモを提供しました。これは、オブジェクトが完全に他のオブジェクトに触れるかどうかを検出し、メソッドが検出したものが返されます。現在のオブジェクトが現在触れているすべてのオブジェクトの配列を返すことを試みています。されている配列私は現在、それに触れるすべてのオブジェクトの配列を返すことができたが、今私は、アレイが必要な型のオブジェクトが含まれているかどうかをチェックするための簡単な/効率的な方法を必要とし、そのよう配列に特定のクラスが含まれている場合、どのように配列を尋ねますか?

if (array.Contains(Mario)) 
    { 
    //Do Work here 
    } 

としてそれが(Mario)が含まれているかどうかをチェックすると、交差するスプライトの配列が返されますが、実際にMario型のオブジェクトが含まれているかどうかを尋ねると「Error 14 'WindowsGame10.Mario'は 'type' '変数' "私はforループでこれを行うことができ、配列内の個々のインデックスif (array[i].GetType() == typeof(Mario))を尋ねることができますが、コード内でこのチェックを行い、同じコードを何度も何度も再入力する必要がある回数は、私はこれを実行するより効率的な方法を学ぶ必要があります。私はコンピュータプログラミングの初年度にあり、C#XNAで作業しています。理解できる解決策が必要です。これを行うより良い方法がある場合は、私に知らせてください。あなたが行うことができますLINQのを使用して

if (array.OfType<Mario>().Any()) 
{ 
+1

あなたはいつもちょうど方法でそのループを包むことができます:

static public bool ContainsType(this Array array, Type type) { int len = array.Length; // Note that putting this in the loop is slightly slower // because the compiler can't assume that a property value // remains constant. for (int i = 0; i < len; i++) { if (array.GetValue(i).GetType() == type) return true; } return false; } 

次のように使用されるでしょう:ちょうど別のアプローチを提供するために、次のような拡張メソッドを定義することができます。 – prelic

答えて

6

あなたは、LINQのOfType()Any()メソッドを使用することができます(LINQを使用せずに)

var marios = array.OfType<Mario>(); 
if (marios.Any()) 
{ 
    //Stuff 
} 
+0

ありがとうございます。これは、私が使用する危険性のあるforループの量を大幅に減らしました。 –

+3

最初の一致が見つかるまで、または一致するものがない場合は配列全体を走査するまで、配列をトラバースしていることに注意してください。 Linqはプログラミングの労力を軽減する素敵な抽象ですが、実際にはループを直接コーディングするよりもわずかに遅くなる可能性があります。多数のゲームオブジェクト(千またはそれ以上)がある場合は、O(n)検索よりも優れたものになるようにストレージ構造を最適化することをお勧めします。 @EricJ。 –

+0

はい - ただし、ストレージメカニズムを変更することなく、このソリューションをループしても大したことはありません。辞書への変更やタイプ別の別々のコレクションの変更は、これがいつどのように使用されるかに応じて最適化される可能性があります。 –

1

ほとんどまっすぐな方法は、isキーワードを使用することです:

foreach (Object obj in array) 
{ 
    if (obj is Mario) 
    { 
     ... 
    } 
} 

更新: あなたは正確にType一致を必要とし、コードの重複を回避したい場合、私は次のようにかなり単純な拡張メソッドがベストだと思う -

public static bool ContainsType<T>(this T[] arr, Type type) 
{ 
    for (int i = 0; i < arr.Length; i++) 
     if (arr[i].GetType().Equals(type)) 
      return true; 
    return false; 
} 

と使用 -

if (array.ContainsType(typeof(Mario))) 
+0

私の理解には(そして私はここから離れているかもしれませんが)Key Refreshは親のリフレクションを扱っています。将来私はこのクラスと対話できないようにするためにmarioの代理人を作ろうとすると、彼らは "ベースのクラスマリオから継承するため、彼らとのやりとりは、"ある "が反映されて動作するためです。 –

+0

@MatthewCrandall:is演算子はReflectionを使用せず、非常に効率的です(http://stackoverflow.com/a/1134104/284240)。 –

+0

@MatthewCrandallそれは継承しているタイプも含まれているということは間違いありませんが、それは望ましくない効果であると私には不透明でした。とにかく、自分の投稿を更新しました。また、私はあなたが間違って相続を反省と呼んでいると信じています。 – Acidic

2

あなただけの、これはiteratioから抜け出すだろう

if(array.Any(a=>a is Mario)) 
{ 
} 

任意のマリオがあるかどうかを知る必要がある場合最初の試合が見つかるとすぐにn

+0

FYI - 私の解決策は、配列全体を(必ず)繰り返し処理するのではなく、Any()呼び出しのために最初のものが見つかるとすぐに中断します。 –

+0

こんにちは、それは分かりませんでした。ありがとうリード。 – labroo

+1

LINQの遅延実行モデルによるものです。 –

1

Linqの回答は素晴らしいです。コードの重複を避け、

Array a = new object[] { "The meaning of life.", 42 }; 
    bool hasString = a.ContainsType(typeof(string)); // true 
    bool hasInteger = a.ContainsType(typeof(int)); // true 
    bool hasChar = a.ContainsType(typeof(char)); // false 
関連する問題