Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Думайте о нем этот путь, если необходимо было сделать такой бросок, и затем добавлять объект типа Foo к списку, список строк больше не последователен. Если бы необходимо было выполнить итерации первой ссылки, Вы получили бы исключение броска класса, потому что, как только Вы поражаете экземпляр Foo, Foo не мог быть преобразован в строку!
Как примечание стороны, я думаю, что было бы более значительно, можно ли сделать обратный бросок:
List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;
я не использовал C# в некоторое время, таким образом, я не знаю, законно ли это, но такой бросок на самом деле (потенциально) полезен. В этом случае Вы идете от более общего класса (объект) к более определенному классу (строка), которая расширяется от общего. Таким образом, если Вы добавляете к списку строк, Вы не нарушаете список объектов.
кто-либо знает или может протестировать, если такой бросок законен в C#?
Это на самом деле так, чтобы Вы не пытались поместить любой нечетный "объект" в свой вариант списка "ol" (поскольку List<object>
, казалось бы, позволил бы) - потому что Ваш код откажет тогда (потому что список действительно List<string>
и только примет объекты Строкового типа). Вот почему Вы не можете бросить свою переменную к более техническому требованию.
На Java это наоборот, у Вас нет дженериков, и вместо этого все - Список объекта во времени выполнения, и действительно можно наполнить любой странный объект в, предположительно строго, введенном Списке. Поиск "Овеществленных дженериков" для наблюдения более широкого обсуждения проблемы Java...
Я думаю, что этот (контравариантность) будет на самом деле поддерживаться в C# 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
Такая ковариантность на дженериках не поддерживается, но можно на самом деле сделать это с массивами:
object[] a = new string[] {"spam", "eggs"};
C# выполняет проверки на этапе выполнения, чтобы препятствовать тому, чтобы Вы поместили, скажем, int
в a
.
Да, Вы можете от.NET 3.5:
List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
Это имеет непосредственное отношение к ковариантности, например, универсальные типы рассматривают как параметры, и если параметры не разрешают правильно к более определенному типу тогда операционные сбои. Импликация такого - то, что Вы действительно не можете бросить к более общему типу как объект. И, как указано Королем, Объект списка не преобразует каждый объект для Вас.
Вы могли бы хотеть попробовать и следующие код вместо этого:
List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);
или:
List<object> ol = new List<object>();
ol.AddRange(sl);
ol (теоретически) скопирует все содержание sl без проблем.
Причина состоит в том, что универсальный класс как List<>
, в большинстве целей, которые рассматривают внешне как нормальный класс. например, когда Вы говорите List<string>()
, в компиляторе говорится ListString()
(который содержит строки). [Технический народ: это чрезвычайно plain-English-ified версия того, что продолжается]
, Следовательно, очевидно, компилятор не может быть достаточно умным для преобразования ListString в ListObject путем кастинга объектов его внутреннего набора.
Вот почему существуют дополнительные методы для IEnumerable, любят, Преобразовывают (), которые позволяют Вам легко предоставлять преобразование для объектов, сохраненных в наборе, который мог быть столь же простым как бросающий от одного до другого.
Вы не можете бросить между универсальными типами с параметрами другого типа. Специализированные универсальные типы не являются частью того же дерева наследования и несвязанные типы - также.
, Чтобы сделать эти предсетевые 3.5:
List<string> sl = new List<string>();
// Add strings to sl
List<object> ol = new List<object>();
foreach(string s in sl)
{
ol.Add((object)s); // The cast is performed implicitly even if omitted
}
Используя Linq:
var sl = new List<string>();
// Add strings to sl
var ol = new List<object>(sl.Cast<object>());
// OR
var ol = sl.Cast<object>().ToList();
// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();
Если Вы используете.NET 3.5, взглянули на Счетное. Метод броска. Это - дополнительный метод, таким образом, можно назвать его непосредственно в Списке.
List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();
Это не точно, что Вы попросили, но должны добиться цели.
Редактирование: Как отмечено Zooba, можно тогда назвать ol. ToList () для получения Списка
Mike - я полагаю, что контравариантность не позволяется в C# ни один
, См. Универсальное различие параметра типа в CLR еще для некоторой информации
Вот еще одно решение до .NET 3.5 для любого списка IList, содержимое которого может быть неявно преобразовано.
public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
List<B> newList = new List<B>();
foreach (D item in list)
{
newList.Add(item);
}
return newList;
}
(На основе примера Зубы)
У меня есть:
private List<Leerling> Leerlingen = new List<Leerling>();
И я собирался заполнить его данными, собранными в List
В конце концов, у меня сработало следующее:
Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();
. Приведите
его к типу, который вы хотите получить IEnumerable
из этого типа, затем приведите тип IEnemuerable
к Список <>
по вашему желанию.