在 foreach 循环中访问 List<object[]> 的数组元素



这就是我所拥有的:

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
}

有没有一种方法可以在不损失代码可读性的情况下实现这一点,或者我应该尝试使用类而不是对象数组?

您需要这样做(操作员优先级问题)

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

然而,我认为在同一个数组中使用不同的对象类型不是一个好的做法。这就是引入泛型List的原因(ArrayList缺乏类型安全性)。

您的代码正在尝试执行以下操作:

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

这是在.Net 2.0之前。它造成了一些问题。

如果您正在使用.NET4,并且不想创建新的类,那么Tuple就是您可以使用的:

List<Tuple<Vector2, Vector4>> markers = new List<Tuple<Vector2, Vector4>>();

你正在做的事情很糟糕。为什么不编程到一个接口,并在列表中迭代呢。然后你就不需要选角了,你可以根据合同做其他事情。在这种情况下,您并不真正知道哪个对象是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();
      ....
}

您绝对应该重构它以使用类。基本上,您需要一个标记列表,每个标记都可以包含一个或多个向量,这些向量依次包含一个或者多个数字。这是一种在不使用继承的情况下实现它的简单方法:

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>

我会编写类,而不是使用内置的结构Vector2Vector4,并让它们实现一个公共接口。这使您能够在声明数据结构时使用特定类型,而不是使用类型object

试试这样的东西:

public class MyVector2 : IVector {
    //...
}
public class MyVector4 : IVector {
    //...
}
public interface IVector {

}

然后声明您的结构如下:

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

如果类型Vector2Vector4是一些自定义类型,而不是来自的System.Windows.Vector2System.Windows.Vector4,则可以对它们进行子类化,并按照上述步骤进行:

public class MyVector2 : Vector2, IVector {
}
public class MyVector4 : Vector4, IVector {
}

只是一个提议。

我决定和Tuple一起去。感谢发帖人的想法,他后来删除了自己的答案。你的英勇事迹将被铭记。

编辑:必须将Vector4更改为Color(alpha通道始终为255)。

结果:

// 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效率,如果这比其他提出的解决方案慢,我会考虑使用它们。

这里可能是一个很好的起点:

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

相关内容