2

I ask because I thought C# required all interfaces to be implemented in the class. Using ILSpy I found that IReadOnlyList.this[int index] indexer implementation wasn't in the class List.

this is an edited snippet of the class declaration(not everything listed)

public class List < T > : IList <T >, IReadOnlyList < T >

List class declaration

IList<T>.this[int index] is there, but not IReadOnlyList<T>.this[int index].

ILSpy search

Just seems weird, how does this compile in the first place? Is there some special sauce in .NET Framework that enables this?

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Alex. A
  • 732
  • 1
  • 7
  • 13
  • 1
    Why use ILSpy when you can see the source code? https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646 – Camilo Terevinto Sep 03 '18 at 00:30
  • Even looking at the actual source code on reference source, I can't find any implementation of IReadOnlyList on List. It's not a partial class, there is only one code file for it. – Alex. A Sep 03 '18 at 00:33
  • 3
    @Alex.A - It's in the source. Line 174 is `public T this[int index]` and that implements `IReadOnlyList`. – Enigmativity Sep 03 '18 at 00:36
  • Ok. If the public indexer this[int index] implements IReadOnlyList, why does it have a setter? IReadOnlyList only defines an indexer with a getter. Wouldn't that normally fail compilation? – Alex. A Sep 03 '18 at 00:51
  • 2
    @Alex [Compiles just fine](http://rextester.com/TDGH79727). Not sure why you think it wouldn't - you have to implement what an interface requires. It doesn't mean you're restricted from implementing more. – ProgrammingLlama Sep 03 '18 at 00:53
  • 2
    @Alex.A no, you need to think of properties and indexers as just a convenience for calling a `Foo GetFoo()` and `void SetFoo(Foo value)` the interface only requires that the get method exists, it does not care if the set method is there or not. – Scott Chamberlain Sep 03 '18 at 00:54
  • 1
    Thanks. I forgot that interfaces only specifies the minimum of what the class has to implement, not the maximum. – Alex. A Sep 03 '18 at 01:13

2 Answers2

2

I think the tool you're using is causing the confusion. The indexer in the list is not implemented explicitly as IList implementation.

public class List<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList
{
    (...)
    public T this[int index] { get; set; }

Here's a simple snippet with a class that implements two interfaces to prove that it's OK to provide a single implementation for two interfaces.

    public interface IOne{void MyMethod();}

    public interface ITwo{void MyMethod();}

    public class MyClass: IOne, ITwo
    {
        public void MyMethod()
        {
            Console.WriteLine("Hello!");
        }
    }

    public static void Main()
    {
        new MyClass().MyMethod();
    }
tymtam
  • 31,798
  • 8
  • 86
  • 126
0

To have a pre-implemented type of IReadOnlyCollection or IReadOnlyList you can use ReadOnlyCollection. Please look at this sample code:

 public void Test()
    {
        IList<int> myList = new List<int>() { 1, 10, 20 };
        IReadOnlyList<int> myReadOnlyCollection = new ReadOnlyCollection<int>(myList);
        GetElement(myReadOnlyCollection,1);
    }


 private int GetElement(IReadOnlyList<int> list,int index)
    {
        return list[index];
    }

//Output: 10
Mohammad Nikravesh
  • 947
  • 1
  • 8
  • 27
  • 1
    Your answer seems to imply that `List` does not implement `IReadOnlyList`. That is incorrect. It does implement it. `Why did you expect to find the implementation of IReadOnlyList in List` https://stackoverflow.com/questions/15262981/why-does-listt-implement-ireadonlylistt-in-net-4-5 – mjwills Sep 03 '18 at 03:23