Почему нет возможного преобразования (общий тип ограничен с интерфейсом)? [Дубликат]

Это говорит о том, что выполняйте немедленно.

, так что если я делаю:

var val = (function(){
     var a = 0;  // in the scope of this function
     return function(x){
         a += x;
         return a;
     };
})();

alert(val(10)); //10
alert(val(11)); //21

Fiddle: http://jsfiddle.net/maniator/LqvpQ/


Второй пример:

var val = (function(){
     return 13 + 5;
})();

alert(val); //18

104
задан Daniel May 5 February 2010 в 16:38
поделиться

2 ответа

Отклонение будет поддерживаться только в режиме safe - фактически, используя способности, которые CLR уже имеет. Поэтому примеры, которые я даю в книге по попытке использовать List<Banana> как List<Fruit> (или что бы это там было), по-прежнему не сработают, но некоторые другие сценарии будут.

Во-первых, это будет поддерживаться только для интерфейсов и делегатов.

Во-вторых, для этого требуется, чтобы автор интерфейса / делегата украшал параметры типа как in (для контравариантности) или out (для ковариации). Наиболее очевидным примером является IEnumerable<T>, который только позволяет вам принимать значения «из» - это не позволяет добавлять новые. Это станет IEnumerable<out T>. Это не повредит безопасности типов, но позволяет вам возвратить IEnumerable<string> из метода, объявленного для возврата IEnumerable<object>, например.

Контравариантность сложнее дать конкретные примеры использования интерфейсов, но это легко с делегатом. Рассмотрим Action<T> - это просто метод, который принимает параметр T. Было бы неплохо легко конвертировать Action<object> в качестве Action<string> - любой метод, который принимает параметр object, будет прекрасным, если вместо него будет представлен string. Конечно, C # 2 уже имеет ковариацию и контравариантность делегатов в некоторой степени, но через фактическое преобразование из одного типа делегата в другой (создание нового экземпляра) - см. Примеры P141-144. C # 4 сделает это более общим, и (я полагаю) избежит создания нового экземпляра для преобразования. (Это будет ссылка вместо этого.)

Надеюсь, что это немного очистит - пожалуйста, дайте мне знать, если это не имеет смысла!

153
ответ дан Jon Skeet 22 August 2018 в 07:53
поделиться
  • 1
    Итак, означает ли это, что если класс объявлен как «List & lt; out t & gt;» & quot; то он НЕ должен иметь функцию-член, такую ​​как «void Add (T obj)»? Компилятор C # 4.0 сообщит об ошибке, верно? – Morgan Cheng 30 October 2008 в 02:24
  • 2
    Морган: Это, конечно, мое понимание, да. – Jon Skeet 30 October 2008 в 23:10
  • 3
    но снова один из ваших ответов здесь, на SO, сразу помог мне улучшить код. Спасибо! – Mark 8 October 2010 в 13:34
  • 4
    @ Ark-kun: Да, я знаю об этом. Следовательно, «все еще не будет работать». в том же предложении. (И я тоже знаю причины). – Jon Skeet 9 June 2013 в 08:27
  • 5
    @JonSkeet Правильно ли, что «вы можете использовать только List<Banana> как IList<Fruit> & quot; как сказал Арк-кун? Если да, то как это возможно, хотя параметр типа интерфейса IList<T> не определен как ковариантный (нет out T, а просто T). – gehho 23 October 2013 в 13:48

Не то, чтобы Джон еще не накрыл его, но вот некоторые ссылки на блоги и видео от Эрика Липперта. Он неплохо объясняет это примерами.

https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c -part-one /

Видео:

https://www.youtube.com/watch?v=3MQDrKbzvqU

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v = St9d2EDZfrg

5
ответ дан kemiller2002 22 August 2018 в 07:53
поделиться
Другие вопросы по тегам:

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