Аргументы типа не могут быть выведены: почему? [Дубликат]

Если вы не инициализировали ссылочный тип и хотите установить или прочитать одно из его свойств, он будет генерировать исключение NullReferenceException.

Пример:

Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.

Вы можно просто избежать этого, проверив, является ли переменная не нулевой:

Person p = null;
if (p!=null)
{
    p.Name = "Harry"; // Not going to run to this point
}

Чтобы полностью понять, почему выбрано исключение NullReferenceException, важно знать разницу между типами значений и ссылочные типы .

Итак, если вы имеете дело со типами значений, NullReferenceExceptions не может произойти. Хотя вам нужно поддерживать оповещение при работе со ссылочными типами!

Только ссылочные типы, как следует из названия, могут содержать ссылки или буквально буквально ничто (или «нуль»). Если типы значений всегда содержат значение.

Типы ссылок (эти должны быть проверены):

  • динамический
  • объект
  • string

Типы значений (вы можете просто игнорировать эти):

  • Числовые типы
  • Интегральные типы
  • Типы с плавающей запятой
  • decimal
  • bool
  • Пользовательские структуры

8
задан Ani 19 October 2010 в 14:33
поделиться

3 ответа

Я понимаю, что вывод типа не является точной наукой

Я не уверен, что согласен. Спецификация довольно подробно.

Мне было интересно, есть ли какое-то фундаментальное «правило», которое я здесь отсутствует

Основное правило, которое вам не хватает вероятно, что ограничения не являются частью подписи. Вывод типа не работает.

На мой взгляд, есть веские причины для этого дизайнерского решения. Однако многие люди считают, что я морально ошибаюсь, полагая, что есть веские причины для этого дизайнерского решения. Если вы заинтересованы в чтении того, что походит на несколько миллионов слов на тему того, прав я или нет, см. Мою статью по этому вопросу и сотни или около того комментариев, в которых говорится, что я не прав:

http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

< blockquote>

Является ли это недостатком процесса вывода?

Возможно, да. На мой взгляд, это разумный выбор, учитывая конкурирующие требования к дизайну. (Те, которые «делают то, что имел в виду пользователь», и «дают ошибки, когда ситуация выглядит неоднозначной».)

- это мое ожидание, что компилятор должен «понять это» в этом случае необоснованно?

№. Вы, кажется, разумный человек, и ваше ожидание, похоже, основано на хороших рассуждениях. Однако вполне возможно иметь разумное ожидание, которое, тем не менее, неудовлетворено. Это был бы один из этих случаев.

Могу ли я изменить сигнатуру метода таким образом, чтобы сделать его одинаково функциональным, но «неочевидным»?

Это будет сложно, поскольку общий тип словаря не является ковариантным или контравариантным в своих преобразованиях. Концепция, которую вы хотите захватить, не легко выражается в системе типов способом, который дает вывод.

Если вы предпочитаете использовать языки с более сложными выводами типа, рассмотрите возможность использования F #. Если вы предпочитаете языки, которые искажают «делать то, что означает пользователь», а не «сообщать об ошибках в двусмысленности», подумайте об использовании VB.

15
ответ дан Eric Lippert 1 September 2018 в 08:34
поделиться

Вывод типа C # не работает с ограничениями или возвращаемыми значениями. Таким образом, вам будет немного удаче с

public static void SomeMethod<TKey, TUnderlyingValue>
    (this IDictionary<TKey, IEnumerable<TUnderlyingValue>> dict)
  { }

Это будет работать, если вы объявите параметр как new Dictionary< string, IEnumerable<int>>(), но не , если вы объявите его new Dictionary<string, List<int>>().

Я должен сказать, что, как я читал раздел 7.5.2 c # spec , кажется, что, поскольку List<int> реализует IEnumerable<int>, вывод типа TUnderlyingValue должен работать. Однако этот раздел не совсем понятен. Я предполагаю, что это не работает через несколько «слоев», так как SomeMethod<T>(IEnumberable<T> val){} будет работать, просто называя его SomeMethod(new List<string>()). Я специально не вижу ничего в спецификации, которая имеет дело с разрешением типа, где U = Ca<Va, Cb<Vb>>, поэтому, возможно, вывод на этом уровне не определен.

4
ответ дан Philip Rieck 1 September 2018 в 08:34
поделиться

Почему бы не оставить тип IEnumerable?

public static void SomeMethod<TKey, TValue>
(this IDictionary<TKey, TValue> dict)
where TValue : IEnumerable { }    
1
ответ дан Pieter van Ginkel 1 September 2018 в 08:34
поделиться
Другие вопросы по тегам:

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