2010-08-13 106 views
1

我希望构造一个匿名类型的列表,通过循环嵌套循环中的两个其他列表来构建匿名类型。构造匿名类型和嵌套循环的通用列表

var myList = new List<???>(); 
foreach (object x in GetAllX()) 
{ 
    if (Process(x)) 
    { 
     foreach (object y in GetAllY(x)) 
     { 
      myList.Add(new { 
       X = x, 
       Y = y 
      }); 
     } 
    } 
} 

我知道我可以构建使用ToList()匿名类型的列表,(见this question),但我不知道怎样才能在上述情况下使用。

请注意,我无法更改GetAllXGetAllY方法。

+0

可能[匿名类的通用列表]的副本(http://stackoverflow.com/questions/612689/a-generic-list-of-anonymous-class) – nawfal 2013-10-17 07:13:01

回答

4

简单的答案是“你不应该”。

有一个哈克招,让你做到这一点:

var myList = new[] { new { X = (object) null, Y = (object) null } }.ToList(); 
myList.Clear(); 
foreach (object x in GetAllX()) 
    // ... 

但它真的会更合理地使用它的目的的方式:

var myList = GetAllX().Where(x => Process(x)) 
    .SelectMany(x => GetAllY(x).Select(y => new { X = x, Y = y })) 
    .ToList(); 

如果你出于某种原因不能使用这种纯功能的风格,或者你发现你必须在多个地方实例化这样的列表,那么你应该声明一个普通的类而不是使用anonymou s类型。请记住,无论如何匿名类型都会编译成类,所以对匿名类型没有性能优势,即使可读性/可维护性的好处也是值得怀疑的,因为如果您不得不使用像这篇文章顶部的hacky这样的技巧。

有人建议使用List<dynamic>,但我建议不要。它严重地妨碍了可维护性,因为在编译时不再检查属性名称和类型(你可能错误地输入了一个并得到运行时错误);它会降低运行时性能,因为每次访问都要经过动态调度程序;而且,一旦你把你的对象放入这个列表中,你就基本上被它们固定为动态的,因为你不能将它们转换回匿名类型。

0

你有两种选择。首先,你可以创建一个具有XY性质的简单类,让你列表类的对象列表,像这样:

class NewClass 
{ 
    public object X; 
    public object Y; 
} 

var myList = new List<NewClass>(); 
foreach (object x in GetAllX()) 
{ 
    if (Process(x)) 
    { 
     foreach (object y in GetAllY(x)) 
     { 
      myList.Add(new NewClass() { 
       X = x, 
       Y = y 
      }); 
     } 
    } 
} 

或者,你可以只使用在C#4.0:

var myList = new List<dynamic>(); 
+0

您可以通过第一个选项获得更强大的类型检查。 – 2010-08-13 01:57:33

0

既然你把X和Y放在同一个列表中,它们必须有一个通用的基类/接口。什么?他们之间没有关系?那你为什么要把它们放在同一个列表中!这不是一个好主意。

IEnumerable<BaseClass> AllXY = 
      GetAllX().Cast<BaseClass>().Union(GetAllY().Cast<BaseClass>()); 
foreach(var base in AllXY) 
{ 
    //do something to base, usually with polymorphism 
} 
+0

为什么?X =类别,Y =该类别中的事物,或者可能是X =目录,Y =该目录中的文件。有许多原因可能会导致为什么在将X和Y分开保存在结果列表中的情况下是一个好主意。 – Justin 2010-08-13 03:32:47

+0

X = direcotires,Y = files,将它们放在一个列表中是没有意义的。 – 2010-08-13 05:07:41

+0

我想你错过了我正在做的事情。 – Justin 2010-08-13 06:52:50

1

这段代码不是实现所需结果的最简单方法吗?

var myList = (from x in GetAllX() 
       where Process(x) 
       from y in GetAllY(x) 
       select new 
       { 
        X = x, 
        Y = y, 
       }).ToList(); 

(Timwi - 我知道这是你的解决方案的“linqified”版本,但我想我会发布它,因为我觉得在这种风格很容易阅读和遵守)