Interestingly, when I go to the definition of IList<T>
in the Visual Studio, it's not the same as the source code on GitHub.
IList<T>
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
ICollection<T>
public interface ICollection<T> : IEnumerable<T>, IEnumerable
Given that ICollection<T>
already includes IEnumerable<T>
and IEnumerable
why does IList<T>
need to include them. Couldn't it be simplified as below?
public interface IList<T> : ICollection<T>
I'm trying to understand a logic behind this long interface chaining.
You can check the source code below to see the differences.
TL;DR: The compiler will compile the class as though it specifically implements all mentioned interfaces as well as all implied/inherited interfaces into the assembly. There is no way for ILSpy, ILDasm, or "Go to definition" to know the difference without actually downloading and showing the original source code.
Since you have now clarified that you used Go To Definition in Visual Studio, there are two tools in scope:
Both takes different approaches to show the contents of a compiled assembly. I believe ILSpy is used behind the scenes in Visual Studio but read on for why that doesn't actually matter.
If we do a simple test in LINQPad:
void Main()
{
}
public interface IA
{
}
public interface IB : IA
{
}
public class Test : IB
{
}
and then ask LINQPad to reflect the code using ILSpy, we get this definition for Test
:
public class Test: IB, IA
Clearly ILSpy shows that Test
implements both, whereas the source just got IA
via IB
.
What about ILDasm? I wrote a .NET 5 assembly using Visual Studio, and then decompiled it using ILDasm, with the exact same code as above:
.class interface public abstract auto ansi ClassLibrary3.IA
{
} // end of class ClassLibrary3.IA
.class interface public abstract auto ansi ClassLibrary3.IB
implements ClassLibrary3.IA
{
} // end of class ClassLibrary3.IB
.class public auto ansi beforefieldinit ClassLibrary3.Test
extends [System.Runtime]System.Object
implements ClassLibrary3.IB,
ClassLibrary3.IA
{
Basically, this is an artifact of how the compiler compiles the source. I don't know enough IL to know if reassembling the interface from Intermediate Language, without mentioning IA
will actually produce the same output but I'll leave that as an excercise.
I also took a look at various sources for this information:
IList
does not but for IList<T>
does