Добавление значения null в список <bool?> Как IList, бросающий исключение
Использование .NET 3.5 и С# 3.0,
IList list = new List<bool?>();
list.Add(null);
Это вызывает исключение ArgumentException, которое просто кажется неправильным.
List<bool?> list = new List<bool?>();
list.Add(null);
Работает отлично.
Является ли это ошибкой в коде Microsoft?
Пример того, как произвести такую ошибку в реальной ситуации:
new JavaScriptSerializer().Deserialize<List<bool?>>("[true, false, null]");
Ответы
Ответ 1
Да, это так. См. http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/abc99fb5-e218-4efa-8969-3d96f6021cee/ для других отчетов. В основном, когда вы получаете доступ к List<bool?>
через его слабо типизированную реализацию IList, он выполняет некоторую проверку типов, прежде чем пытаться добавить элемент во внутреннее хранилище, - и он проверяет этот тип неправильно для типов с нулевым значением.
Ответ 2
Это "по дизайну" и явно так. Причина в том, что List<T>
имеет явную реализацию IList
. Он фильтрует значения, переданные различным методам, для выполнения нулевой проверки. Логика в основном такова:
if (default(T) != null && value == null) { throw ... }
В этом случае значение по умолчанию для типа значения (и nullable - тип значения) не равно null, поэтому оно не разрешено.
Ответ 3
Ха! Это смешно. Я полагаю, что это связано с идеей о том, что nullable bool, строго говоря, реализуется как структура, а IList ожидает объект, и, возможно, он ожидает, чтобы вставить bool или что-то еще. Джон Скит, где ты? Мы нуждаемся в вас! (краны рубиновые тапочки 3 раза)
Ответ 4
Когда вы вызываете метод Add в IList
с нулевым значением, это пустая ссылка, которую вы передаете методу, а не значение NULL. Нулевая ссылка не может быть преобразована в значение с нулевым значением.
Метод Add ожидает нечто, содержащее bool
или bool?
. Поскольку вы не можете ввести нулевое значение, вы не можете создать объект, который можно использовать для добавления нулевого значения в IList
.
Если вы используете общий интерфейс IList<bool?>
вместо этого, нет проблем с добавлением значения:
IList<bool?> list = new List<bool?>();
list.Add(null);
Ответ 5
Как уже отмечалось, в реализации метода IList.Add(объект объекта) в классе List <T>
в .NET 3.5 (а может быть и раньше) есть ошибка. Дело в том, что метод IList.Add(объект объекта) пытается проверить, что объект, который мы пытаемся добавить, является объектом, совместимым с аргументом Generic типа <T>
, который терпит неудачу, когда мы пытаемся добавить null к списку типов допустимых значений.
Мое обходное решение включает отражение, получая и вызывая метод Add (T item) из объекта List.
IList list = new List<bool?>();
MethodInfo addMethod = list.GetType().GetMethod("Add");
addMethod.Invoke(list, new object[] { null });
Ответ 6
Вы смешиваете Generic List<T>
с не общим IList
. List<T>
наследуется от IList<T>
, а не от IList
.