настроен 24 април '16 в 18:36
Не е ясно как да се конструира covariant и contravariant. Примерът показва, че делегата може да получи референция към две методи с различни входни и изходни параметри. Тук е промяната в ChangeIt ковариация = IncrB; и Contravariant ChangeIt промяна = IncrA;? Като цяло, няма ясна дефиниция на covariant и contravariant, те са твърде объркваща. - NaughtyBrain 24 апр '16 в 19:20
За да започнете, нека да погледнем какво е отклонението.
Да предположим, че имаме два класа, кола и BMW. Ясно е, че BMW има разделение на кола. всеки BEHA една машина.
Обикновено това казват: "всеки път, когато използвате колата. Можете да използвате и БМВ-то. » Това всъщност е почти вярно, но не съвсем.
Пример: ако имате списък с машини, не можете да го използвате вместо списък на BMW. Защо? И ето защо. Нека имате Списък
Ако имахме списък на достъпна само за четене. проблемите просто не е бил:
Така че това, което правим? Въпреки факта, че BMW - автомобил, BMW списък не е задължително списък с машини. И тук е списък на BMW, е достъпна само за четене, след като в списъка на машини.
Сега обратно към дисперсията. Ние говорим за ковариацията в най-общ смисъл, ако нещо се променя по същия начин. В случай на класове на наследството, че можем да използваме вместо кола BMW. и просто, колкото можем, вместо IEnumerable
Добре, че е дълго въведение, а сега обратно към темата: ковариация делегати. Да предположим, че имаме делегат, в зависимост от типа автомобил. Промени в своето определение в кола BMW. дали е възможно да се използва нов делегат да замени стария?
Да помислим логично. Ако имаме делегат:
(Car Приема вход и произвежда друг случай на кола.), След това дали е възможно вместо да замени функцията описваща делегати този тип:
Не, разбира се, тъй като делегат може да получите на входа на всяка функция, както и нашата функция иска само да BMW. Така че няма ковариация: тази функция не може да се използва там, където искате делегата.
Но ако нашият вариант Тип данни (тоест, кола) е само в позицията на типа на връщане:
след това на негово място, можете да използвате функцията по следния начин:
(Ако се обърне всеки автомобил, BMW също е хубаво).
Това е ковариацията на делегатите, където от вас в кода изисква да делегира, можете да дадете вместо covariant делегат.
Примерен код, че той използва:
Contravariance работи по друг начин: там можете да използвате делегат работа с вида на основата, където се очаква да се делегира на производния клас. Това работи за аргументи на функция:
Тя работи по същите причини като ковариацията: Ако тестера се вписва всеки тип машина, тя може да работи с BMW, също.
Всеки от родово параметри тип делегат или интерфейс трябва да се маркира като covariant и contravariant. Това не води до някакви непредвидени последствия, но ви позволява да използвате вашите делегати в повече сценарии и ще ви даде възможност да се направи отливка на променливата обща делегата от същия тип, с различен параметър делегат тип.
Тип параметри могат да бъдат:
- Инвариантна. параметър тип не може да бъде променено.
- Contravariant. параметър тип могат да бъдат превърнати от класа на
класове, получени от него. В C #, а contravariant вид
определена ключова дума инча параметър Тип contravariant
Тя може да се появи само в позицията за въвеждане, като например
метод аргументи. - Ковариация. тип аргумент може да бъде изчислена от класа на един от своите основни класове. В C #, а covariant вид, обозначен с ключова дума навън. Covariant родово тип параметър може да се появи само в позицията на изхода, например, като стойността на връщане на метода.
Да предположим, че следният тип делегат:
Тук, параметър T-тип маркирана дума инча което го прави contravariant и параметър тип дума TResult маркирана. вземане на ковариация. Нека съобщиха от следните променливи:
Това може да доведе до вид MyDelegate с други параметри, типове:
Това предполага, че fn1 се отнася до функция, която се обект и се връща ArgumentException. Частично fn2 се опитва да се отнася до метод, който отнема String и връща изключение. Тъй като може да премине метод String, което изисква тип обект (от тип String е получен от обекта) и резултатите от метода връщат ArgumentException. може да се тълкува като Изключение (тип ArgumentException е получен от Изключение), кодът представени тук се изготвя, и по време на безопасност тип компилация ще се поддържа.
Забележка: дисперсията е валидно само ако компилаторът е в състояние да установи способността да конвертирате между видовете връзки. С други думи, по-значителни отклонения не се прилага за видове нужда опаковката на (бокс).
Свързани статии