【问题标题】:Unified way to access arrays with different types访问不同类型数组的统一方式
【发布时间】:2012-07-10 21:22:44
【问题描述】:

假设我有以下课程:

class Master {
  int x;
  int y;

  public int X { get { return x; } set { x = value; } }
  public int Y { get { return y; } set { y = value; } }
}

class Sub1:Master {
  int z;

  public int Z { get { return z; } set { z = value; } }
}

class Sub2:Master {
  int w;

  public int W { get { return w; } set { w = value; } }
}
class Sub3:Master {
  int t;

  public int T { get { return t; } set { t = value; } }
}

然后我定义了三个不同的数组,每个Sub*类型一个:

List<Sub1> array1;
List<Sub2> array2;
List<Sub3> array3;

最后,我需要一种以统一方式访问所有实例的方法。想法是使用一个新数组List&lt;T&gt;[] array4 = new[] {array1, array2, array3}; 并使用int 作为索引,因此我不必为属性XY 编写三倍的常用操作。

但是,我不能这样做,因为三个数组的类型不同。我可以使用什么?

【问题讨论】:

  • 你试过 List[] masterList = new List[]{array1, array2, array3};

标签: c# .net arrays generic-list


【解决方案1】:

它们共享一个基本类型,因此您可以创建一个List&lt;Master&gt; 来保存所有三种类型的实例。

最终,所有对象都共享相同的基类型object,因此始终可以使用List&lt;object&gt;,但在这种情况下,它们共享层次结构中更高的基类型,因此您可以使用Master

要为所有实例创建一个列表,您可以执行以下操作:

var all = new List<Master>(array1.Count + array2.Count + array3.Count);

all.AddRange(array1);
all.AddRange(array2);
all.AddRange(array3);

首先,您创建一个新列表,并且由于您已经知道预期容量应该是多少,因此您可以使用接受int capacity 的构造函数重载。这样,当您添加其他集合时,不必调整列表的大小,从而提高代码效率。

附带说明,我知道这可能只是示例代码,但您应该根据变量所代表的内容命名变量,因此应保留像 array* 这样的名称,以供真正代表数组时使用。

【讨论】:

    【解决方案2】:

    List实现了非泛型接口ICollectionIEnumerableIList,所以你可以创建一个IList[] array4 = { array1, array2, array3 };的新数组

    或者,在您的列表中添加元素时,您可以(也)将它们添加到另一个 Master 类型的列表中,像这样

    List<Sub1> array1 = new List<Sub1>();
    List<Sub2> array2 = new List<Sub2>();
    List<Sub3> array3 = new List<Sub3>();
    List<Master> array4 = new List<Master>();
    
    ...
    
    public void AddSub1(Sub1 sub)
    {
        array1.Add(sub);
        array4.Add(sub);
    }
    
    public void AddSub2(Sub2 sub)
    {
        array2.Add(sub);
        array4.Add(sub);
    }
    
    public void AddSub3(Sub3 sub)
    {
        array3.Add(sub);
        array4.Add(sub);
    }
    

    这样,你可以遍历array4的所有元素:

    foreach(Master master in array4)
    {
       master.DoSomething();
    }
    

    【讨论】:

      【解决方案3】:

      您实际上可以通过使用 IEnumerable&lt;T&gt; 被声明为 IEnumerable&lt;out T&gt; 以及 Enumerable.ElementAt&lt;T&gt; 为实现 IEnumerable&lt;T&gt;runtime 类型优化 @987654326 的事实来完成这项工作@。这让你可以这样做:

      var x = new IEnumerable<Master>[] {array1, array2, array3};
      x[0].ElementAt(4);
      

      同时仍然可以持续访问列表中的各个元素。感觉有点笨拙,但应该仍然有效。

      如果它适合正在完成的工作,我认为更好的选择是创建一个泛型方法,并在每个列表中调用该泛型方法:

      private void MainMethod()
      {
          List<Sub1> array1 = new List<Sub1>();
          List<Sub2> array2 = new List<Sub2>();
          List<Sub3> array3 = new List<Sub3>();
          DoOperation(array1);
          DoOperation(array2);
          DoOperation(array3);
      }
      
      private void DoOperation<T>(List<T> list) where T: Master
      {
          // do work here
          list[0].X = 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多