11

Possible Duplicate:
count vs length vs size in a collection

Really strange:

C# arrays such as the following

double[] test = new double[1];

support the Length property to get the size of the array. But arrays also implement an IList interface:

IList<double> list = test;

However, the IList interface provides also a Count property. How come the array ("test" in this case) doesn't?

Edit: Thanks to all of you who pointed out that it is in fact the ICollection interface (not IList) which provides the Count property, and also that this is due to explicit implementation of the interface.

Community
  • 1
  • 1
Chris
  • 2,057
  • 2
  • 16
  • 20
  • 2
    ... vs **Capacity** vs **ItemCount** (like `ColumnCount` in `ListView` vs `Columns.Count`) vs **NumItems** (`NumIndices` in `EnvDTE`) vs **CountOfItems** (`CountOfLines` in `EnvDTE`) vs etc ... I just *love* the consistency in MS's frameworks. :) – user541686 Jan 22 '11 at 19:38

4 Answers4

18

Simply, they chose to call it Length, and implement Count via explicit interface implementation -something like:

int ICollection.Count { get { return Length; } }
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
9

It was a design choice about Naming, not semantics.

Arrays have a Length property, as does the String.

Length signals immutable: You cannot Add to or Remove from an array.

Lists and other containers have a Count property that can usually change.

Oh, and if you call list.Append(1.1); you will get a not supported exception.

H H
  • 263,252
  • 30
  • 330
  • 514
  • 10
    Length by no means signals immutable; `MemoryStream` (actually, lots of stream implementations), `StringBuilder`, etc – Marc Gravell Jan 22 '11 at 19:22
  • @Marc: I didn't mean to imply a very strict rule. Streams are another domain, and I think StringBuilder.Length is a concession to String. I still think it loosely holds for containers. – H H Jan 22 '11 at 19:27
5

The Count property is hidden using the explicit interface declaration style, for example like this in a class definition:

int IList.Count {
    get {
        // ...etc...
    }
}

You can access methods and properties hidden like this using a type cast, e.g.

((IList<double>) myArray).Count
Jon Grant
  • 11,369
  • 2
  • 37
  • 58
4

Types inheriting from Array obtain implementations of IList<T> at run-time (how this is possible, don't ask me):

In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IEnumerable<T> generic interfaces. The implementations are provided to arrays at run time, and therefore are not visible to the documentation build tools. As a result, the generic interfaces do not appear in the declaration syntax for the Array class, and there are no reference topics for interface members that are accessible only by casting an array to the generic interface type (explicit interface implementations). The key thing to be aware of when you cast an array to one of these interfaces is that members which add, insert, or remove elements throw NotSupportedException.

In effect the IList<T> implementation acts like an explicit implementation, as Marc explained in his answer. This is why you can access certain members of IList<T> from the result of a cast but not from a variable typed as T[] specifically.

Community
  • 1
  • 1
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • That last line was in essence already in the question. – H H Jan 22 '11 at 19:42
  • @Henk: You're right; I meant to highlight the "explicit implementation" part; including the code example was superfluous and only distracted from that point. I removed it. – Dan Tao Jan 22 '11 at 20:18