Ковариантность это некий неявный Upcast каждого элемента массива.
Контравариантность это некий неявный DownCast каждого элемента массива.
Массивы элементов ссылочных типов ковариантны но, не контравариантные.
Массивы элементов структурных типов не ковариантные и не контравариантные.
Массив — именованный набор однотипных переменных, расположенных в памяти непосредственно друг за другом, доступ к которым осуществляется по индексу.
Типы массива являются ссылочными типами, производными от абстрактного базового класса Array.
Индекс массива — целое число, либо значение типа, приводимого к целому, указывающее на конкретный элемент массива.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
using System; // Ковариантность массивов в C#. namespace Arrays { public interface IAnimal { void Voice(); } public class Dog : IAnimal { public void Voice() { Console.WriteLine("Gav-Gav"); } public void Jump() { Console.WriteLine("Jump"); } } class Program { static void Main() { Dog[] dogs = { new Dog(), new Dog(), new Dog() }; for (int i = 0; i < dogs.Length; i++) { dogs[i].Voice(); dogs[i].Jump(); } Console.WriteLine(new string('-', 10)); IAnimal[] animal = dogs; // Ковариантность. for (int i = 0; i < dogs.Length; i++) { animal[i].Voice(); //animal[i].Jump(); } Console.WriteLine(new string('-', 10)); dogs = (Dog[])animal; // Не является Контрвариантностью. for (int i = 0; i < dogs.Length; i++) { dogs[i].Voice(); dogs[i].Jump(); } // Delay. Console.ReadKey(); } } } |
Ключевое слово params, позволяет задать параметр метода, принимающий переменное количество аргументов.
Параметр с ключевым словом params, должен быть только один и стоять последним в списке аргументов метода.
1 2 3 |
void Method(int item1, params int[] item2) { } |
Индексаторы позволяют индексировать экземпляры класса или структуры так же, как массивы. Индексаторы напоминают свойства, но их методы доступа принимают параметры.
Метод set автоматически срабатывает тогда, когда свойству пытаются присвоить значения. Это значение представлено ключевым словом value.
Метод get автоматически срабатывает тогда, когда мы пытаемся получить значение.
1 2 3 4 5 6 7 8 9 10 |
int [] array= new int [3] { 1,2,3 }; public int this [int index] { get{return array[index];} set{array[index]=value;} } |
- Индексаторы не обязаны использовать в качестве индекса целочисленное значение, конкретный механизм поиска определяет разработчик.
- Индексаторы можно перегружать.
- Индексаторы могут иметь более одного формального параметра, например, при доступе к двухмерному массиву.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
class MyClass { private int[] array = new int[5]; // Индексатор. public int this[int index] { get // Аксессор. { return array[index]; } set // Мутатор. { array[index] = value; } } } class Program { static void Main() { MyClass my = new MyClass(); my[0] = 1; my[1] = 2; my[2] = 3; my[3] = 4; my[4] = 5; Console.WriteLine(my[0]); Console.WriteLine(my[1]); Console.WriteLine(my[2]); Console.WriteLine(my[3]); Console.WriteLine(my[4]); // Delay. Console.ReadKey(); } |
Если в классе встречаются два и более индексаторов, то они должны отличаться друг от друга типом и количеством индексов, своего рода реализация перегрузкой индексатора.
Ковариантность не применима к массивам элементов структурных типов.
1 2 3 4 5 6 7 8 |
static void Main() { Dog[] dogs = { new Dog(), new Dog(), new Dog() }; //IAnimal[] animal = dogs; // Ковариантность. //dogs = array; // Контрвариантность. int[] vector = new int[3] { 1, 2, 3 }; //object[] array = vector; // Ковариантность } |