Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
1 / 1 / 1
Регистрация: 14.10.2015
Сообщений: 94

Ковариантность и контрвариантность

01.06.2018, 15:41. Показов 1822. Ответов 4

Студворк — интернет-сервис помощи студентам
Добрый день, в книге дошел до ковариантности и контравариантности и появился вопрос. Если с ковариантностью все понятно, потому что если возвращается производный класс, то он обязательно содержит методы базового класса, то вот с контравариантностью возникают проблемы.

Смотрите пример:

C#
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
public class A
{
     public void biba(B arg)
     {
       arg.bubi(5.0f);
     }
}
 
public class b:A
{
    public bubi(float arg)
    {
       Console.WriteLine(arg);
    }
}
 
public class NUNU
{
   public delegate void DelegateFunction(B arg);
   static void Main()
    {
        A first= new A();
        B second= new B();
 
        DelegateFunction+=A.biba;
        DelegateFunction(A); //выйдет ошибка, нуу по идее должна, так как объекту А ничего неизвестно про функцию bubi
 
    }
}
И вот как бы контравариантность выходит не совсем работает.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.06.2018, 15:41
Ответы с готовыми решениями:

Ковариантность и контрвариантность
Обьясните по простому, на сколько это возможно, что такое Ковариантность и контрвариантность. Где это применяется и нужно ли заостоять...

Ковариантность (и контрвариантность) массивов
Найдите и исправьте ошибки в методе Main using System; namespace Less05_task01 { class Program { static void Main(...

Ковариантность и Контрвариантность - что это?
Прошу помочь мне объяснить эти два понятия, ещё читая Шилдта не понял, что эта за возможность такая, а теперь столкнулся c подобными...

4
1123 / 794 / 219
Регистрация: 15.08.2010
Сообщений: 2,185
01.06.2018, 16:22
Цитата Сообщение от Ermitash Посмотреть сообщение
Смотрите пример:
который даже не скомпилируется..
Цитата Сообщение от Ermitash Посмотреть сообщение
так как объекту А ничего неизвестно про функцию bubi
и не дожно быть ничего известно, аргумент бибы должен быть А
0
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
01.06.2018, 17:33
может проще будет исходить из того, что ты сможешь сделать с текущим T, если он будет понижен/повышен внутри метода, и внешне:

# out, т.е. означает "вне", значит работаем с отдаваемым значением. Если у нас есть условный тип B унаследованый от A, то отдавая B в условную переменую A мы не нарушаем логики.

C#
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
class Program
    {
        static void Main(string[] args)
        {
            IFactory<A> _factory = new Factory<B>();
            A modelA = _factory.Create();
            //B modelB = _factory.Create(); -- так работать не будет
            B modelB = _factory.Create() as B; //-- так будет
            Console.WriteLine(modelA.GetType()); //-- выведеть ConsoleApp1.B
            _factory = new Factory<С>(); //можем нашу фабрику заменить на другого наследника
            modelA = _factory.Create(); //все еще коректно
            //С modelС = _factory.Create(); -- так работать не будет
            //B modelB = _factory.Create(); -- тоже не катит
            modelB = _factory.Create() as B; //-- так будет, но в modelB запишеться null (читаем про as)
            С modelС = _factory.Create() as C; //-- работает, и modelС  не пустое
        }
    }
 
    class A { }
    class B : A { }
    class С : A { }
 
    interface IFactory<out T>
        where T : new()
    {
        T Create();
    }
 
    class Factory<T> : IFactory<T>
        where T : new()
    {
        public T Create() => new T();
    }
У нас есть некий класс, создающий модель. Мы в переменную _factory записали обьект, который на самом деле создает B, но возращать будет как будто создали просто А. Єто допустимо т.к. B производное от А, и логика не нарушается.

Добавлено через 10 минут
# in означает что мы можем ожидать извне более "высокий" тип, который все же будет наследником базового. С возможностью приведения тут все с точностью до наоборот

C#
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
class Program
    {
        static void Main(string[] args)
        {
            IPrinter<B> _printer = new Printer<A>();
            _printer.PrintField(new B()); // -- все ок
            //_printer.PrintField(new A()); -- так работать не будет
        }
    }
 
    class A
    {
        public string Field;
    }
    class B : A { }
 
    interface IPrinter<in T>
        where T : A
    {
        void PrintField(T model);
    }
 
    class Printer<T> : IPrinter<T>
        where T : A
    {
        public void PrintField(T model) => Console.WriteLine(model.Field);
    }
Вроде не логично, что мы для более высокого B передаем принтер с более общим A, но т.к. данный тип используется только для передачи в качестве параметра, то все ок -- B является A, и в методе PrintField в реализации Printer ничего не нарушается.

Добавлено через 5 минут
Цитата Сообщение от Ermitash Посмотреть сообщение
DelegateFunction(A);
конкретно тут выдаст ошибку, т.к. ожидает вхождение такое же или наследника, а не предка.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
03.06.2018, 10:57
Лучший ответ Сообщение было отмечено Ermitash как решение

Решение

Цитата Сообщение от Ermitash Посмотреть сообщение
И вот как бы контравариантность выходит не совсем работает.
Вы просто неправильно поняли идею контравариантности.
Контравариантность делегатов в параметрах означает, что если меется делегат вида void Func(B arg), то переменной его типа можно присвоить ссылку на метод void Foo(A arg), где B : A.

В вашем же примере никакая контравариантность не используется, потому как делегату вида void DelegateFunction(B arg) вы присваиваете ссылку на метод void biba(B arg) — параметры имеют один и тот же тип.
Вместо контравариантности вы пытаетесь передать ссылку на А в метод, принимающий B, что просто-напросто запрещено правилами языка, когда В наследуется от А.
1
1 / 1 / 1
Регистрация: 14.10.2015
Сообщений: 94
06.06.2018, 12:31  [ТС]
kolorotur, спасибо большое!) Благодаря тебе я понял. Тогда да, это логично, потому что производный класс содержит также и базовый.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.06.2018, 12:31
Помогаю со студенческими работами здесь

Обобщенный интерфейс ковариантность
Господа, подскажите пожалуйста по коду. Вот ради эксперимента набросал код, но не пойму, почему метод GetNameObj возвращает объект типа a1...

Ковариантность и контравариантность делегатов
возникают ошибки при выводи,подскажите в чем ошибка? или где можно найти ответ на данный вопрос. using System; namespace...

Ковариантность обобщений - разобрать код
Почему тут Figure становится типом Circle? Должен же быть Shape, мы же апкастим его до Shape в строчке IContainer&lt;Shape&gt;...

Что такое ковариантность и контрковариантность?
Может кто-нибудь объяснить коротко своими словами что такое ковариантность и контрковариантность? Добавлено через 1 минуту И как эти...

Ковариантность и контравариантность обобщенных интерфейсов
Добрый вечер, скажите, кто-то может пояснить ПРАКТИЧЕСКУЮ цель ковариантности и контравариантности в обобщенных интерфейсах? Как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru