В C#, почему Список не может <представить объект в виде строки> быть сохраненным в Списке <объектная> переменная

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

82
задан user 27 September 2012 в 04:25
поделиться

12 ответов

Думайте о нем этот путь, если необходимо было сделать такой бросок, и затем добавлять объект типа Foo к списку, список строк больше не последователен. Если бы необходимо было выполнить итерации первой ссылки, Вы получили бы исключение броска класса, потому что, как только Вы поражаете экземпляр Foo, Foo не мог быть преобразован в строку!

Как примечание стороны, я думаю, что было бы более значительно, можно ли сделать обратный бросок:

List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;

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

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

38
ответ дан Mike Stone 24 November 2019 в 09:19
поделиться

Это на самом деле так, чтобы Вы не пытались поместить любой нечетный "объект" в свой вариант списка "ol" (поскольку List<object>, казалось бы, позволил бы) - потому что Ваш код откажет тогда (потому что список действительно List<string> и только примет объекты Строкового типа). Вот почему Вы не можете бросить свою переменную к более техническому требованию.

На Java это наоборот, у Вас нет дженериков, и вместо этого все - Список объекта во времени выполнения, и действительно можно наполнить любой странный объект в, предположительно строго, введенном Списке. Поиск "Овеществленных дженериков" для наблюдения более широкого обсуждения проблемы Java...

1
ответ дан Valters Vingolds 24 November 2019 в 09:19
поделиться

Я думаю, что этот (контравариантность) будет на самом деле поддерживаться в C# 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

2
ответ дан MattValerio 24 November 2019 в 09:19
поделиться

Такая ковариантность на дженериках не поддерживается, но можно на самом деле сделать это с массивами:

object[] a = new string[] {"spam", "eggs"};

C# выполняет проверки на этапе выполнения, чтобы препятствовать тому, чтобы Вы поместили, скажем, int в a.

1
ответ дан Constantin 24 November 2019 в 09:19
поделиться

Да, Вы можете от.NET 3.5:

List<string> sl = new List<string>();
List<object> ol = sl.Cast<object>().ToList();
5
ответ дан Tamas Czinege 24 November 2019 в 09:19
поделиться

Это имеет непосредственное отношение к ковариантности, например, универсальные типы рассматривают как параметры, и если параметры не разрешают правильно к более определенному типу тогда операционные сбои. Импликация такого - то, что Вы действительно не можете бросить к более общему типу как объект. И, как указано Королем, Объект списка не преобразует каждый объект для Вас.

Вы могли бы хотеть попробовать и следующие код вместо этого:

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 без проблем.

6
ответ дан Jon Limjap 24 November 2019 в 09:19
поделиться

Причина состоит в том, что универсальный класс как List<>, в большинстве целей, которые рассматривают внешне как нормальный класс. например, когда Вы говорите List<string>(), в компиляторе говорится ListString() (который содержит строки). [Технический народ: это чрезвычайно plain-English-ified версия того, что продолжается]

, Следовательно, очевидно, компилятор не может быть достаточно умным для преобразования ListString в ListObject путем кастинга объектов его внутреннего набора.

Вот почему существуют дополнительные методы для IEnumerable, любят, Преобразовывают (), которые позволяют Вам легко предоставлять преобразование для объектов, сохраненных в наборе, который мог быть столь же простым как бросающий от одного до другого.

11
ответ дан Rex M 24 November 2019 в 09:19
поделиться

Вы не можете бросить между универсальными типами с параметрами другого типа. Специализированные универсальные типы не являются частью того же дерева наследования и несвязанные типы - также.

, Чтобы сделать эти предсетевые 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();
14
ответ дан Zooba 24 November 2019 в 09:19
поделиться

Если Вы используете.NET 3.5, взглянули на Счетное. Метод броска. Это - дополнительный метод, таким образом, можно назвать его непосредственно в Списке.

List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();

Это не точно, что Вы попросили, но должны добиться цели.

Редактирование: Как отмечено Zooba, можно тогда назвать ol. ToList () для получения Списка

36
ответ дан Ray 24 November 2019 в 09:19
поделиться

Mike - я полагаю, что контравариантность не позволяется в C# ни один

, См. Универсальное различие параметра типа в CLR еще для некоторой информации

3
ответ дан Matt Sheppard 24 November 2019 в 09:19
поделиться

Вот еще одно решение до .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;
}

(На основе примера Зубы)

0
ответ дан 24 November 2019 в 09:19
поделиться

У меня есть:

private List<Leerling> Leerlingen = new List<Leerling>();

И я собирался заполнить его данными, собранными в List В конце концов, у меня сработало следующее:

Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();

. Приведите его к типу, который вы хотите получить IEnumerable из этого типа, затем приведите тип IEnemuerable к Список <> по вашему желанию.

0
ответ дан 24 November 2019 в 09:19
поделиться
Другие вопросы по тегам:

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