Why Array Doesn't Have 'Add' Method? - Blog CSHARK Why Array Doesn't Have 'Add' Method? - Blog CSHARK

IT Ocean blog

Blog subscription

22/04/19

Why Array Doesn't Have 'Add' Method?

Why Array Doesn't Have 'Add' Method?

When you think about this is sounds pretty straightforward. When we initiate an Array we have to declare the size of the array. We cannot extend the size of an existing array, so Add method doesn’t have any sense. Right?

Take a look:

int[] temp = new int[5];

But do you know that this array uses abstract class Array?

Let me show you how does Array look like in code [1]. The Array class has the following declaration:

public abstract class Array :  IList, …

Array implements IList. IList has method Add. So why can’t we use Add method in Array?

Let me show you a similar situation which we have in Array. I create Foo class which implements IFoo (Array implements IList).

   class Program
   {
       static void Main(string[] args)
       {
           var foo = new Foo();
           Console.WriteLine(foo.Value());
       }
   }

   public interface IFoo
   {
       int Value();
   }


   public class Foo : IFoo
   {
       public int Value()
       {
           return 1;
       }
   }

That will work.

What will happen if we try to use 'Add method' on array?

class Program
    {
        static void Main(string[] args)
        {
            int[] temp = new int[5];
            temp.Add(2);
        }
    }

We will get an error message:

'int[]' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'int[]' could be found

Beside or that error IntelliSense will not show us 'Add' method.

Let’s check how does the implementation of 'Add' method in Array class look like:

        int IList.Add(Object value)
        {
            throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
        }

Let us do the very same thing in our code:

    class Program
    {
        static void Main(string[] args)
        {
            var foo = new Foo();
            Console.WriteLine(foo.Value());
        }
    }

    public interface IFoo
    {
        int Value();
    }


    public class Foo : IFoo
    {
        int IFoo.Value()
        {
            return 1;
        }
    }

In that case, we will get an error message:

'Foo' does not contain a definition for 'Value' and no accessible extension method 'Value' accepting a first argument of type 'Foo' could be found

So our class implements IFoo, but method Value() is not accessible.

Is it possible to access 'Add' method in array? Yes, our array can access Add method but first, we need to cast the array to IList.

    class Program
    {
        static void Main(string[] args)
        {
            int[] temp = new int[5];
            ((IList)temp).Add(2);
        }
    }

In that case, will get a NotSupportedException exception.

In our Foo class we can access Value method in the same way:

        static void Main(string[] args)
        {
            var foo = new Foo();
            Console.WriteLine(((IFoo)foo).Value());
        }

How is it possible that class implements interface, but method from the interface is not accessible. The answer to that question is an Explicit interface [2].

Explicit interface member implementations have different accessibility characteristics than other members. Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. However, since they can be accessed through an interface instance, they are in a sense also public.

Let me demonstrate one more thing.

    public class Foo : IFoo
    {
        int GetValue()
        {
            return Value();
        }

        int IFoo.Value()
        {
            return 1;
        }
    }

In that piece of code we will get an error:

The name 'Value' does not exist in the current context

If we want to call Value() method we need to do it in a different way:

    public class Foo : IFoo
    {
        int GetValue()
        {
            return ((IFoo)this).Value();
        }

        int IFoo.Value()
        {
            return 1;
        }
    }

Value method is not accessible from the object itself. It is accessible after casting to interface.

[1] https://referencesource.microsoft.com/#mscorlib/system/array.cs

[2] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces