我不会使用这些迭代所有元素的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 方法链接。