Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a consistent .Count / .Length property for C# generic collections?

List<T> has the .Count property, where as T<> arrays .Length instead. I presume this is because arrays are fixed-length whereas the others aren't, but the difference in syntax can still be frustrating.

If you refactor from an array to list, it therefore gives "does not contain a definition for .Length" errors, and it seems a waste of time having to change it when .Count and .Length are essentially the same.

Is it there a good way to deal with this ? Is it possible to extend List<T> to add an .Length property that's an alias for .Count for instance, and vice-versa for the generic array ? And would this be a bad idea for any reason ?

like image 791
Michael Low Avatar asked Dec 21 '22 15:12

Michael Low


2 Answers

You can use the Count method provided by LINQ.

This is optimised to use the Count property provided by the ICollection<T> interface where possible (or the non-generic ICollection interface too in .NET 4). So arrays, List<T> etc will all be optimised.

var yourList = new List<string> { "the", "quick", "brown", "fox" };
int count1 = yourList.Count();  // uses the ICollection<T>.Count property

var yourArray = new[] { 1, 2, 4, 8, 16, 32, 64, 128 };
int count2 = yourArray.Count();  // uses the ICollection<T>.Count property

var yourEnumerable = yourArray.Where(x => x > 42);
int count3 = yourEnumerable.Count();  // no optimisation, iterates the sequence

Alternatively, if you wanted a consistent count property of some kind without running the risk of iterating an entire sequence in the non-optimised case then you could create your own extension methods. (I personally wouldn't go down this route.)

int count4 = yourList.GetCount();  // uses the ICollection<T>.Count property
int count5 = yourArray.GetCount();  // uses the ICollection<T>.Count property
int count6 = yourEnumerable.GetCount();  // compile-time error

// ...

public static class CollectionExtensions
{
    public static int GetCount<T>(this ICollection<T> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return source.Count;
    }

    public static int GetCount(this ICollection source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return source.Count;
    }
}
like image 121
LukeH Avatar answered Mar 14 '23 01:03

LukeH


You could put your array in a variable of type IList<T>. (arrays implement this interface)

You can then use the array exactly the way you use any other IList<T> (although Add and Remove will throw exceptions, since arrays are fixed-length)

like image 35
SLaks Avatar answered Mar 14 '23 02:03

SLaks