![](/img/trans.png)
[英]How can I create a collection with a sequential number as one field from another collection in C#
[英]How can I create an empty collection from an anonymous collection most elegantly in C#?
如果我有一個由LINQ創建的匿名類型
var ans = from r in someList where someCondition(r) select new { r.a, r.b };
創建空匹配集合的最佳方法是什么,這樣我就可以將元素移動到新集合:
var newans = ?
foreach (r in ans) { if (complicated(r)) newans.Add(r); }
有什么方法可以使用Enumerable.Empty <>()嗎?
我不會使用ans.Where(x => false).ToList()
版本來遍歷所有不需要的元素; ans.Take(0).ToList()
一點,因為當您查詢內存中的序列(LINQ to Objects)時,它實際上並沒有遍歷整個列表。
如果您正在使用LINQ to SomethingElse,事情會有些問題,因為它實際上可能會執行類似SELECT TOP(0) * FROM ...
或SELECT * FROM ... WHERE 1 = 0
。 不好。
因此,以下幫助程序方法將為您提供幫助:
public static class AnonymousTypeExtensions
{
public static List<T> ToEmptyList<T>(this IEnumerable<T> source)
{
return new List<T>();
}
}
var newans = ans.ToEmptyList();
話雖如此,如果您唯一的願望是將ans
某些元素復制到新列表中,那么最好使用
var newans = (from a in ans where isComplicated(a) select a).ToList();
要么
var newans = ans.Where(a => isComplicated(a)).ToList();
如果您不需要實際的List<T>
,而IEnumerable<T>
就足夠了,那么您可以完全省去ToList
了。 提醒您,每次在這樣的枚舉上進行遍歷時,都會一次又一次執行Where(a => isComplicated(a))
。 調用ToList
確保只執行一次。
如果您不只是想要List<T>
,而是更一般的話,事情就會變得復雜得多。 例如,該方法是否應返回ans
變量的靜態類型或其運行時類型? 此外,除了盲目調用new C()
之外,沒有許多集合的“默認”版本。 但這通常不會起作用。 不可能調用new ReadOnlyCollection<T>()
,因為它不存在(而且該集合將被密封,因此無法填充)。 而且,如果您使用的是HasSet,是否不應該將原始的比較器用於空副本,而不是默認的比較器?
但是,對於最簡單的情況,您可以嘗試:
public static class CollectionExtensions
{
public static TCollection AsEmpty<TCollection>(this TCollection source)
where TCollection : ICollection, new()
{
return new TCollection();
}
}
請注意,這是一個編譯時解決方案,它返回變量類型的默認集合。 如果可能的話。 例如ans = from r in somesource select new { ... }
將具有靜態類型IEnumerable<...>
。 這里沒有默認實例可以創建。 同樣, select
返回的運行時類型是System.Core.dll的私有類型,沒有默認構造函數,並且還是只讀的類似游標的類型。
所以我對此的看法是:不要去那里。 不要過度概括,堅持使用ToEmptyList之類的簡單解決方案,甚至更好,堅持使用簡單的LINQ方法鏈。
我沒有嘗試過,但是
var newans = from r in ans where false select r;
似乎是一種生成正確類型的IEnumerable的方法(但不是可以“添加”到的集合-可以將其列出)。
就是說,如果您使用的是LINQ,似乎不太可能擁有問題中包含的“ foreach-if-.add”代碼,
var newans = from r in ans where isComplicated(r) select r;
要么
var newans = ans.Where(isComplicated);
沒有?
var newans = ans.Where(false).ToList()
將執行此操作。
無法使用Enumerable.Empty
因為無法顯式傳遞匿名類型作為泛型參數。
使用var newans = ans.ToList();
它將每個枚舉的對象復制到一個新列表中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.