I wouldn't use the ans.Where(x => false).ToList()
versions these iterate over all elements, which you don't need; ans.Take(0).ToList()
is a little better, as this one doesn't actually iterate over the entire list when you're querying over in-memory sequences (LINQ to Objects).
If you are using LINQ to SomethingElse, things are a little problematic, because it might actually execute something like SELECT TOP(0) * FROM ...
or SELECT * FROM ... WHERE 1 = 0
. Not good.
So the following helper method will help you:
public static class AnonymousTypeExtensions
{
public static List<T> ToEmptyList<T>(this IEnumerable<T> source)
{
return new List<T>();
}
}
var newans = ans.ToEmptyList();
Having said that, if your only desire is to copy some elements of ans
into a new list, you're better of with
var newans = (from a in ans where isComplicated(a) select a).ToList();
or
var newans = ans.Where(a => isComplicated(a)).ToList();
If you don't need an actual List<T>
, and an IEnumerable<T>
is enough, you might get away with omitting the ToList
altogether. Mind you, every time you foreach over such an enumerable, Where(a => isComplicated(a))
is executed again and again. The call to ToList
makes sure you only execute it once.
If you don't want this just for List<T>
, but more general, things get a lot more complicated. For example, should the method return the static type of the ans
variable or its runtime type? Also, there is no such thing as a "default" version of many collections, apart from blindly calling new C()
. But that won't work generally. It's not possible to call new ReadOnlyCollection<T>()
, because it doesn't exist (and the collection would be sealed anyway, so it cannot be filled). And if you're using a HasSet, shouldn't you be using the original's comparer for your empty copy rather than the default comparer?
However, for the simplest case, you could try:
public static class CollectionExtensions
{
public static TCollection AsEmpty<TCollection>(this TCollection source)
where TCollection : ICollection, new()
{
return new TCollection();
}
}
Note that this is a compile-time solution which returns a default collection of the variable's type. If at all possible. For instance ans = from r in somesource select new { ... }
will have the static type IEnumerable<...>
. There's no default instance here to create. Also, the runtime type returned by select
is private to System.Core.dll, doesn't have a default constructor, and is a read-only cursor-like type anyway.
So my opinion on this one is: don't go there. Don't try to over-generalize, stick to simple solutions like ToEmptyList or even better, stick to plain LINQ method chaining.