Как добавить элемент в список, когда у меня есть доступ только к его объекту?

Где-то в моем приложении у меня есть общий список, созданный из другой сборки с использованием отражения. У меня есть доступ только к объекту этого списка. Я имею в виду, что у меня есть Object objectOfList, и я знаю, что это общий список значений (например, значения int или float). Мне нужно добавить элементы в этот список. Как мне это сделать?

Поскольку я не знаю, какой тип общего списка, я попытался привести objectOfList к списку объектов, но он выдает исключение:

(objectOfList as List<object>).Add(value); // value is an integer here

Он выдает исключение нулевой ссылки.

Обновлять

Это может быть int float или любой другой тип. Я не знаю, какой это тип, когда я пишу код. Это пользователь, который выбирает тип списка из UI, после чего список создается.


person a.toraby    schedule 07.02.2016    source источник
comment
Может ли это когда-нибудь быть List<object> или всегда будет List<int> или List<float>? В этом случае вам нужно использовать тип value, т.е. ((List<int>)objectOfList).Add(value);   -  person Lee    schedule 07.02.2016
comment
@Lee Это может быть int float или любой другой тип. Я не знаю, какой это тип, когда я пишу код. Это пользователь, который выбирает тип списка из UI, после чего список создается.   -  person a.toraby    schedule 07.02.2016
comment
Да, но всегда ли это будет тот же тип, что и value, а не подтип? В этом случае вы можете просто использовать тип value. Если тип элемента списка является супертипом value, вместо этого вы можете привести его к IList.   -  person Lee    schedule 07.02.2016


Ответы (4)


Как указал Ли, вы должны использовать фактический тип, а не object. Рассмотрим следующее:

object someList = new List<int>();
(someList as List<object>).Add(1);

Это вызовет NullReferenceException, но

(someList as List<int>).Add(1);

не.

Дополнительная информация о as:

Оператор as похож на операцию приведения. Однако, если преобразование невозможно, as возвращает значение null вместо возбуждения исключения.

как (справочник по C#)

Есть еще одна вещь, которую вы можете попробовать, а именно: отказаться от поддержки безопасности универсального типа List<T> с помощью неуниверсального интерфейса IList. Это позволит вам делать то, что вы хотите, но выдаст System.ArgumentException, если типы разные:

(someList as IList).Add(1); //ok
(someList as IList).Add("hello");  //throws exception
person Ric    schedule 07.02.2016

Список является инвариантным, поэтому вы можете вернуть его только к списку с тем же типом элемента, например.

int value = 4;
object source = new List<int>();
((List<int>)source).Add(value);

Если вы знаете, что тип элемента всегда будет соответствовать типу value, и вы знаете тип value статически, то вы можете выполнить приведение.

Если вы знаете, что тип элемента списка может быть супертипом value, вы можете вместо этого вызвать IList.Add, который по-прежнему безопасен, например.

object source = new List<Animal>();
var g = new Giraffe();
((IList)source).Add(g);

обратите внимание, что в этом случае вы не можете преобразовать source в List<Giraffe>.

Если вы не знаете этот статический тип value, вам также придется выполнить приведение к IList и быть готовым к обработке исключения при вызове Add.

person Lee    schedule 07.02.2016

Object objectOfList нельзя преобразовать в List<object>, поэтому оператор as возвращает null.

Если вы инициализировали его как List<Object> objectOfList или Object objectOfList = new List<Object>();, вы не получите нулевую ссылку. Например.

    Object objectOfList = new List<object>();
    (objectOfList as List<object>).Add(5); 

(Пример скрипта)

person NikolaiDante    schedule 07.02.2016

Попробуйте вернуть список объектов к тому, что было. если это был список, то:

Список lo = ((Список)objectOfList)

Таким образом, вы можете работать со списком. Затем вы можете узнать, какой это тип списка, с помощью этого метода:

objectOfList.ToString() или objectOfList.GetType().ToString()

person Anthony Dekimpe    schedule 07.02.2016