5

これは私が持っているものです:

List<object[]> markers = new List<object[]>();

object[] marker = new object[2];
marker[0] = new Vector2(1, 2);
marker[1] = new Vector4(1, 2, 3, 4);
markers.Add(marker);

foreach (var item in markers)
{
    int x = (Vector2)item[0].X; // Error: 'object' does not contain a definition
                                // for 'X' and no extension method 'X' accepting
                                // a first argument of type 'object' could be
                                // found (are you missing a using directive or
                                // an assembly reference?)
    // other stuff
}

コードの可読性を失わずにこれを機能させる方法はありますか、それともオブジェクト配列の代わりにクラスを使用する必要がありますか?

4

7 に答える 7

4

これを行う必要があります(演算子の優先順位の問題)

((Vector2)item[0]).X;

ただし、同じ配列に異なるオブジェクト型を含めることは良い習慣ではないと思います。そのため、一般的な List が導入されました (ArrayList の型安全性の欠如)。

あなたのコードは次のようなことをしようとしています:

ArrayList vectors = new ArrayList { new Vector2(22, 33), new Vector4(223, 43, 444, 33}};

これは.Net 2.0より前でした。そして、それはいくつかの問題を引き起こしていました。

于 2012-07-09T18:30:14.077 に答える
1

.NET 4 を使用していて、新しいクラスを作成したくない場合は、Tuple を使用できます。

List<Tuple<Vector2, Vector4>> markers = new List<Tuple<Vector2, Vector4>>();
于 2012-07-09T18:35:17.847 に答える
1

あなたがしていることはひどいです。インターフェイスにプログラムして、そのリストを反復処理しないのはなぜですか。その後、キャストは必要なく、契約に基づいて他のことを行うことができます。この場合、実際にはどのオブジェクトが vector2 または vector4 なのかわかりません。あなたは見つけることができますが、それは本当に醜いでしょう。

これは、より柔軟で、拡張性があり、保守しやすいものです。私はあなたが何をしているのか本当に知りませんが、私はこれで行きます.

私は次のように何かをします:

interface IVector<T>
{
   List<T> Someobjectcollections
   void YourCommonOperation()

}

class Vector2 : IVector<Vector2>
{
 // override

}

class Vector4 : IVector<Vector4>
{
   // override
}

List<IVector> markers = new List<IVector>();

...


foreach (var item in markers)
{ 
     items.commonoperation();

      ....
}
于 2012-07-09T18:35:19.857 に答える
1

クラスを使用するには、これを絶対にリファクタリングする必要があります。基本的に、マーカーのリストが必要です。各マーカーは、1 つ以上の数値を順番に含む 1 つ以上のベクトルを保持できます。これは、継承を使用せずに実現する簡単な方法です。

public class Marker
{
    public List<Vector> { get; set; }
}

public class Vector
{
    public int[] Numbers { get; private set; }

    public Vector(params int[] numbers)
    {
        Numbers = numbers;
    }
}

その後、簡単に使用できますList<Marker>

于 2012-07-09T18:36:57.037 に答える
1

タプルで行くことにしました。後で彼の答えを削除したポスターへのアイデアに感謝します。あなたの勇敢な行為は記憶されます。

編集:(アルファチャンネルは常に255でした)に変更Vector4する必要がありました。Color

結果:

// declaration
List<Tuple<Vector2, Color>> markers = new List<Tuple<Vector2, Color>>();

// adding items
Tuple<Vector2, Color> marker = new Tuple<Vector2, Color>(
    new Vector2(x, y), Color.FromNonPremultiplied(250, 200, 150, 100));       
markers.Add(marker);

// retrieving item values
foreach (var item in markers)
{
    int x = item.Item1.X;
    int y = item.Item1.Y;
    Color mycolor = item.Item2;
}

動作しますが、CPU 効率についてはまだテストしていません。これが他の提案されたソリューションよりも遅いことが判明した場合は、代わりにそれらを使用することを検討します。

于 2012-07-09T19:29:47.273 に答える
1

組み込みの構造体を使用する代わりにクラスを作成し、それらに共通のインターフェイスVector2Vector4実装させます。これにより、 type を使用する代わりに、データ構造を宣言するときに特定の型を使用できますobject

次のようなことを試してください:

public class MyVector2 : IVector {

    //...
}

public class MyVector4 : IVector {

    //...
}

public interface IVector {


}

次に、次のように構造を宣言します。

List<IVector> list = new List<IVector>();
IVector[] arr = new IVector[someSize];

タイプ と が と ではなくカスタム タイプである場合はVector2、それらVector4をサブクラス化し、上記と同じように進めることができます。System.Windows.Vector2System.Windows.Vector4

public class MyVector2 : Vector2, IVector {

}

public class MyVector4 : Vector4, IVector {

}

ただの提案。

于 2012-07-09T18:33:45.567 に答える
0

これは良い出発点かもしれません:

public class Markers
{
    public Vector2 V2 { get; set; }
    public Vector4 V4 { get; set; }

    public Markers() {}
}
于 2012-07-09T18:34:59.860 に答える