Контравариантные делегаты оценивают типы

Кто-либо может пролить свет на то, почему контравариантность не работает с типами значения C#?

Ниже не работает

private delegate Asset AssetDelegate(int m);

internal string DoMe()
{
    AssetDelegate aw = new AssetDelegate(DelegateMethod);
    aw(32);
    return "Class1";
}

private static House DelegateMethod(object m)
{
    return null;
}
7
задан Jack Kada 9 June 2010 в 13:57
поделиться

2 ответа

Проблема в том, что int не является объектом .

Целое число может быть помещено в объект. Результирующий объект (также известный как int в рамке), конечно, является объектом, но это уже не совсем int.

Обратите внимание, что выражение « равно », которое я использую выше, не то же самое, что оператор C # - . Мое выражение « is » означает, что «можно преобразовать в неявное преобразование ссылки ». Это значение выражения « is » используется, когда мы говорим о ковариации и контравариантности.

Тип int неявно преобразуется в объект, но это не ссылочное преобразование. Это должно быть упаковано в коробку.

Дом неявно преобразуется в Актив посредством преобразования ссылки. Нет необходимости создавать или изменять какие-либо объекты.

Рассмотрим пример ниже. Обе переменные house и asset ссылаются на один и тот же объект. Переменные integer и boxedInt , с другой стороны, имеют одно и то же значение, но ссылаются на разные вещи.

House house = new House();
Asset asset = house;

int integer = 42;
object boxedInt = integer;

Упаковка и распаковка не так проста, как может показаться. Он имеет множество тонкостей и может неожиданным образом повлиять на ваш код. Смешивание бокса с ковариацией и контравариантностью - простой способ поразить любого.

5
ответ дан 7 December 2019 в 09:57
поделиться

Я согласен с комментарием Энтони Пеграма - он основан на ссылочных типах, имеющих другой объем памяти, чем типы значений: CLR может неявно использовать класс одного типа как класс своего супертипа, но когда вы начинаете использовать значение типов, CLR нужно будет поместить ваше целое число в ящик, чтобы оно могло работать вместо объекта.

Если вы все равно хотите, чтобы это работало, у меня есть тенденция заключать объявление в выражение:

AssetDelegate aw = new AssetDelegate((m) => DelegateMethod(m));

Я не знаю, является ли это хорошей практикой или нет с точки зрения синтаксиса, но помните, что бокс и распаковка стоит дорого.

1
ответ дан 7 December 2019 в 09:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: