Understanding ICollection Implementation and Interfaces

I am familiar with the fact that the interface contains only the signatures of methods, delegates or events. Methods are implemented in a class that implements the interface. a class that implements the interface MUST implement its methods.

I created a general list. when I look at the List declaration, I see that it inherits ICollection, and ICollection has a signature method: object SyncRoot {get; } why I do not see the implementation of SyncRoot in the List class?

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable { public List(); public List(IEnumerable<T> collection); public List(int capacity); } 

I expect to see: public object syncRoot() in the above? Also, if I open it with JustDecompile (Telerik), I see that it is implemented, but as private . Did I miss something?

+4
source share
1 answer

This is an explicit implementation of the interface, as @dtb points out. This means that the SyncRoot element SyncRoot displayed if used from a link of type ICollection , but not of a link of type List

 var l = new List<int>(); // compiler error var sr1 = l.SyncRoot; ICollection c = l; // works var sr2 = c.SyncRoot; 

This is an explicit implementation of the interface. If for some reason you wanted to define the basic behavior for the interface reference, but the specialized behavior for your class reference (for example, changing the return type will be more specific, which is usually not valid with a simple overload), you can do this. Or, if you want to implement an interface for obsolete purposes, but want to hide a method or property that is no longer useful in your implementation.

Thus, if you look at the decompiled code, you will see a declaration like:

 object ICollection.SyncRoot { ... } 

Thus, it implements SyncRoot for the SyncRoot interface, making it visible through any ICollection link to the List<T> object, but hides it for any other link (not ICollection ) to the List<T> >> object.

It is also very useful when working with legacy interfaces such as IEnumerable . For example, if you want to support IEnumerable<T> , you must also support IEnumerable , but both of them have GetEnumerator() methods that differ in return type. For instance:

 public class MySpecialList<T> : IEnumerable<T> { // if we access from any other reference, we get the new, generic // interface public IEnumerator<T> GetEnumerator() { // your actual implementation } // so if we access from a reference of IEnumerable, we get older, // non-generic interface IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

Since we cannot have two methods (overloads) that return different values ​​but have the same signature, we can tell the class that GetEnumerator() means one when used with IEnumerable obsolete links, and something completely different ( and better) for all other links:

 var x = new MySpecialList<int>(); IEnumerable y = x; // returns the generic enumerator var genericEnum = x.GetEnumerator(); // since called from an IEnumerable, gets legacy enumerator var legacyEnum = y.GetEnumerator(); 
+6
source

Source: https://habr.com/ru/post/1389306/


All Articles