C# – Get Count of array that converted to dynamic in c#

c

Consider this code:

  static void Main(string[] args)
  {
      var ints=new List<int> {10,11,22};
      Something(ints);//Output:Count is:3
      Something(new int[10]); //'System.Array' does not contain
                              //  a definition for 'Count'
      Console.ReadLine();     
  }
  static void Something(ICollection collection)
  {
      dynamic dynamic = collection;
      Console.WriteLine("Count is:{0}", dynamic.Count);
  }

When pass a List all thing is ok. But when pass array and convert to dynamic i get this error:'System.Array' does not contain a definition for 'Count'.

I know what is my solution but i want to know why compiler has a this behaviors?

Best Answer

Something(new int[10]);

static void Something(ICollection collection)
{
    //The dynamic keyword tells the compilier to look at the underlying information
    //at runtime to determine the variable's type.  In this case, the underlying 
    //information suggests that dynamic should be an array because the variable you
    //passed in is an array.  Then it'll try to call Array.Count.
    dynamic dynamic = collection;
    Console.WriteLine("Count is:{0}", dynamic.Count);

    //If you check the type of variable, you'll see that it is an ICollection because
    //that's what type this function expected.  Then this code will try to call 
    //ICollection.Count
    var variable = collection;
    Console.WriteLine("Count is:{0}", variable.Count);
}

Now that we can understand why dynamic.Count is trying to call System.Array.Count. However, it's still unclear why Array.Count is not defined when Array implements System.Collections.ICollection which has a Count method. Array does in fact implement ICollection correctly, and it does have a Count method. However, consumers of Array.Count do not have permission to access the Count property without explicitly casting the Array to an ICollection. Array.Count is implemented with a pattern known as explicit interface implementation where Array.Count is explicitly implemented for ICollection. And you may only access the count method by casting your variable to an ICollection with this pattern. This is reflected in the docs for Array. Look for the "Explicit Interface Implementations" section.

var myArray = new int[10];
//Won't work because Array.Count is implemented with explicit interface implementation
//where the interface is ICollection
Console.Write(myArray.Count);
//Will work because we've casted the Array to an ICollection
Console.Write(((ICollection)myArray).Count);