Why System.Array class implements IList but does not provide Add()
Asked Answered
I

7

11

This code:

int[] myArr = { 1, 2 };
myArr.Add(3);

throws the following error on Build:

error CS1061: 'System.Array' does not contain a definition for 'Add' and no extension method 'Add' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)

IList interface has the Add() method, but why the Array does not implement it?

UPDATE: I see from the answers that it DOES implement it explicitly, OK, I get it, thank you, I should better stick to the question:

Why Array does not actually provide Add(), OR, better, why did it have to implement IList in the first place? Instead of implementing IList, it could be another interface (e.g. IArray) which could have ONLY the useful for Array members of IList -e.g. IsFixedSize, IsReadOnly, IndexOf()... just a thought.

Infamous answered 30/6, 2016 at 8:34 Comment(5)
If you cast it to an IList, you'll be able to call Add (classes can implement some interfaces explicitly which means that you only get access to (all of) the interfaces methods when treating it as that interface). You'll be disappointed though. Arrays have a fixed size.Biretta
Then why does not the language simply remove the :IList from Array class signature?Infamous
It doesn't. Array implements IList - but if you want to use it as an IList, you have to cast it to a variable of that type.Biretta
@Damien_The_Unbeliever, sorry I corrected the question, I meant why it does not remove it!Infamous
Does this answer your question? Why array implements IList?Upturn
A
9

Yes, it seems that it should have been a better design if System.Array had implemented IReadOnlyList or alike interface. However, IReadOnlyList<T> appeared in .Net 4.5 while System.Array stays from the initial .Net 1.0. Microsoft, IMHO, did their best and hid Add via explicit interface implementation

http://referencesource.microsoft.com/#mscorlib/system/array.cs,156e066ecc4ccedf

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

So you can't do

int[] myArr = { 1, 2 };

myArr.Add(3);

but you can insist on using Add (and get NotSupportedException thrown) via

((IList) myArr).Add(3);

Or even

if (!myArr.IsFixedSize) {
  // we have very strange array, let's try adding a value to it
  ((IList) myArr).Add(3);
}
Askari answered 30/6, 2016 at 9:2 Comment(0)
K
12

Why Array does not actually provide Add()?

Array has fixed size, so you cannot add new element(s).

The number of dimensions and the length of each dimension are established when the array instance is created. These values can't be changed during the lifetime of the instance. https://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

Why did it have to implement IList in the first place?

Definition of IList: Represents a non-generic collection of objects that can be individually accessed by index.

https://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx

Array is accessed by index and IList accommodate this index, which is why Array implements IList.

For reference: Why array implements IList?

Kermitkermy answered 30/6, 2016 at 8:37 Comment(2)
Then why does it implement IList (which has Add)?Infamous
@Infamous you could see here: https://mcmap.net/q/21283/-why-array-implements-ilistKermitkermy
A
9

Yes, it seems that it should have been a better design if System.Array had implemented IReadOnlyList or alike interface. However, IReadOnlyList<T> appeared in .Net 4.5 while System.Array stays from the initial .Net 1.0. Microsoft, IMHO, did their best and hid Add via explicit interface implementation

http://referencesource.microsoft.com/#mscorlib/system/array.cs,156e066ecc4ccedf

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

So you can't do

int[] myArr = { 1, 2 };

myArr.Add(3);

but you can insist on using Add (and get NotSupportedException thrown) via

((IList) myArr).Add(3);

Or even

if (!myArr.IsFixedSize) {
  // we have very strange array, let's try adding a value to it
  ((IList) myArr).Add(3);
}
Askari answered 30/6, 2016 at 9:2 Comment(0)
T
3

It does provide Add, but by throwing a NotSupportedException (see MSDN), because the size of an array is fixed.

The reason why you get a compilation error, instead, is because the interface is implemented explicitly, so if you want to call the method you need to cast to IList. See this C# guide about explicit interface implementation.

Tram answered 30/6, 2016 at 8:39 Comment(0)
I
3

Though a class implementing an interface must implement all members of the interface, it can implement them explicitly:

public class MyList<T> : IList<T>
{
    // ... shortened for simplicity
    void ICollection<T>.Add(T item) {  } // explicit implementation
}

If you implement the method this way, it won't be visible on instances of MyList<T>:

MyList<int> list = new MyList<int>();
list.Add(5); // would NOT compile
((IList<int>)list).Add(5); // can be compiled

So if you have an int[] you could do that:

int[] array = new int[0];
((IList<int>)array).Add(5);

It will compile, but at runtime a NotSupportedException will be thrown because arrays have fixed size and you cannot add a new element to an array as it's size is determined on initialization (new int[0]).

Idolatrous answered 30/6, 2016 at 8:42 Comment(3)
Add() is not part of ICollectionVanzant
@Vanzant yes it is: reference sourceKillingsworth
You're right. I referred to the non-generic version, which is implemented (explicitly) by Array in questionVanzant
S
2

System.Array class implements IList but does not provide Add()

Of course it does via explicit implementation (there is no way to implement interface and not implement some members).

Why the array implements IList?

Well, mainly to indicate that it supports indexer.

But in fact array implements one of the valid IList usages. The IList interface has a property called IsFixedSize, which according to the documentation

Gets a value indicating whether the IList has a fixed size.

and then

A collection with a fixed size does not allow the addition or removal of elements after the collection is created, but it allows the modification of existing elements.

So array implementation returns IsFixedSize = true and throws NotSupportedException inside Add, Insert, Remove and RemoveAt methods.

Slut answered 30/6, 2016 at 9:0 Comment(2)
Thank you! This is closer to the answer that I need.. I have not accepted an answer yet, because I would like a reason why IList was put there in the first place! There could be another interface (e.g. IArray) which could have ONLY the useful for Array members of IList -e.g. IsFixedSize, IsReadOnly, IndexOf()-Infamous
You are right. AFAIC BCL designers considered such alternatives and decided to take this path. Same for generic IList<T> which also has such drawbacks. Starting from .NET 4.5, the IReadOnlyList<T> is closest to what array is (but it lacks indexer setter).Slut
R
1

According to msdn:

IList.Add(Object)

Calling this method always throws a NotSupportedExceptionexception.

Array Class - see explicit interface implementation section

Array has this method. To call this method you should explicitly cast to IList. This method can't be called, because array has fixed size and this size can't be dynamically changed.

Ricardoricca answered 30/6, 2016 at 8:44 Comment(0)
C
1

IList is implemented in three different categories:

  • Readonly
  • Variable size
  • Fixed size

Obviously the Array type is a fixed size implementation of IList. The reason why you cannot access the Add() method from an Array is because the method is implemented explicitly:

public class A : IList {
    public void IList.Add(object o){
         ...
    }
}

This means you need to cast your array to an IList before you're able to use the Add method (even though it will throw an non-supported exception).

You might say this is a bad design, and many people would agree with you on that.

Read more on explicitly defined interfaces: https://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

Cupriferous answered 30/6, 2016 at 8:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.