Recently, I was interested in the structure of such an ancient .Net interface as IList. Why it interested me is a separate long story, about which I, probably. I'll tell you next time.
To study this interface in more detail, I first decided to see what methods it declares. Taking advantage of the reflection:
foreach(var tp in typeof(IList).GetMembers()) Console.WriteLine(tp.Name);
... I got the following results:
get_Item set_Item Add Contains Clear get_IsReadOnly get_IsFixedSize IndexOf Insert Remove RemoveAt Item IsReadOnly IsFixedSize
As you can easily guess, the prefixes are designated getter and setter of the interface properties, that is, we have. In addition to all the methods, there are three more properties: Item with the ability to write and read and two reodonly properties IsReadOnly and IsFixedSize. In addition, the incomprehensible duplication of names is noticeable: get_IsReadOnly // IsReadOnly, get_IsFixedSize // IsFixedSize, get_Item // set_Item // Item. In order to deal with this, I had to change the code a little and, in addition to the class properties themselves, also print the names of the types of properties. The result is the following code:
foreach(var tp in typeof(IList).GetMembers()) Console.WriteLine("{0} -- {1}", tp.Name, Enum.GetName(tp.MemberType.GetType(), tp.MemberType));
This code has given me a more detailed idea of that. what the interface contains:
get_Item -- Method set_Item -- Method Add -- Method Contains -- Method Clear -- Method get_IsReadOnly -- Method get_IsFixedSize -- Method IndexOf -- Method Insert -- Method Remove -- Method RemoveAt -- Method Item -- Property IsReadOnly -- Property IsFixedSize -- Property
So, it became clear that get_IsReadOnly is a getter method of the IsReadOnly property (which is a separate member of the interface, along with a method), like get_IsFixedSize is a method called when reading the IsFixedSize property. The Item property has here both a setter and a getter, that is, it can be accessed as by reading it. and changing.
Having understood this, I immediately asked myself a question: what will happen if the methods for the properties are already predefined.
Quickly concocted the first example, I was convinced. that such code will not compile:
public class Test1 { public int A { get; set; } public int get_A() { return 0; } }
The compiler gives the following error:
Type 'TestArray.Test1' already reserves a member called 'get_A' with the same parameter types
More interesting was the second property Item. My guess is that the property with this name hides the indexer was correct and I was able to concoct a second non-compiled class, this time with the indexer:
public class Test2 { public int Item { get; set; } public int this[int num] { get { return 0; } } }
This time, the description of the error was somewhat different, but the essence of the problem was also clear:
The type 'TestArray.Test2' already contains a definition for 'Item'
However, the reverse attempts to “trick” the compiler by explicitly implementing the methods necessary for the indexer were not successful. The following two class examples compiled without problems.
public class Test4 { public int Item { get; set; } } public class Test3 { public Test3 get_Item(int index) { return this; } public void set_Item(int index, Test3 value) { } }
However, an attempt to access class instances using an indexer resulted in a compilation error:
Cannot apply indexing with [] to an expression of type 'TestArray.Test4'
In this way. The compiler checks for the presence of the indexer syntax during compilation, which prevents us from using this clever way to define our own indexer.
')
From a small investigation we can draw the following conclusions:
- The C # compiler uses a fairly simple and obvious algorithm to generate the names of internal methods when using such syntactically “sugar” constructions as the indexer and property setter / getter.
- Even without inventing complex names for your methods, you can get a problem with name collisions, which will not be so easy to realize without knowing the details of the internal .Net device.
- The Item property and its corresponding setters and getters are converted by the compilers to the syntax of the postfix operator "square brackets" (= indexer), which is syntactic sugar for the get_Item () construct.
If you like the article. then in the next article I will tell you what interested the IList interface.