2010-08-13 108 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」版本,但我想我會發布它,因爲我覺得在這種風格很容易閱讀和遵守)