簡體   English   中英

如何在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM