Array is not IList, or is it? [duplicate]
Asked Answered
A

3

7

Why can i pass an array to method accepting IList resulting in getting error when trying to use this interface (array does not support Add() obviously)

using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        string[] thisIsArray = ["A", "B"];
        IsThisBug(thisIsArray);
    }
    
    public static void IsThisBug(IList<string> array) {
        array.Add("Hello");
    }
}
Animalcule answered 3/9 at 8:53 Comment(1)
One of Microsoft's more egregious violations of the Liskov Substitution Principle (at least technically - there's the IsReadOnly property which does mitigate a bit; I still don't like the design though).Sucrose
M
9

It is often useful enough to support such an interface - even if not every method can be fully implemented; for example, unlike the more restrictive ICollection, IList also adds the this[int index] {get;set;} indexer that an array can support - so if the array only implemented ICollection, some other useful features would be lost. It also has the .IsFixedSize property, which is what you should be checking before attempting to use .Add(...), so the NotSupportedException isn't a surprise.

Maury answered 3/9 at 8:59 Comment(8)
IsFixedSize? Should be IsReadOnly. Should not change to much but IsFixedSize sounds so indirect.Suppliant
I think you mean to use IsReadOnly rather than IsFixedSizeSucrose
There is no IsFixedSize property on the generic IList<T>, is this the proper way I should be using IList<T>? IList<string> x = ["A"]; IList y = (IList)x; if (!y.IsFixedSize) { x.Add("hmm"); } ((sorry, no idea how to place code snippet in comments here...))Animalcule
@Suppliant (responding to now-deleted comment) no, IList<T> does not implement IList; many types that implement IList<T> also implement IList, but that's not quite the same statement; and yes, there's a bit of a discoverability gap in that caseMaury
@Animalcule for code formatting in comments: ` backticks - i.e. `foo` is fooMaury
I needed a second to realize that but your reading skills are faster then that.Suppliant
@Demo: Actually it's the non-generic IList interface that has the IsFixedSize property. The generic ICollection<T>.IsReadOnly returns true for an array, indicating that ICollection<T>.Add/Remove/Clear are not supported. And yes, it's super confusing that the non-generic IList has a combo of IsReadOnly/IsFixedSize instead, returning false/true for an array, indicating that IList.this[] is supported but the other mutating members are not.Riot
Idk readOnly seems also confusing. I wouldn't expect for something readOnly to be mutable (as array is). dotnetfiddle.net/f4jBl1 and to have different meaning for array (mutable but of fixed size), immutable list (not mutable). My takeaways are from this: A) this is intended behavior, B) Adding to IList<> is more complicated than I've knownAnimalcule
S
1

It's not a bug, Array indeed implements IList, but in the way, that some operations throw NotSupportedException

Spasmodic answered 3/9 at 9:1 Comment(0)
E
0

Array does indeed implement IList except it specifically throws an exception on Add which you can see in the source

Elvinelvina answered 3/9 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.