【问题标题】:How to add item to a list when I only have access to its object?当我只能访问其对象时,如何将项目添加到列表中?
【发布时间】:2016-02-07 18:17:01
【问题描述】:

某处 在我的应用程序中,我有一个通用列表,它是使用反射从另一个程序集创建的。我只能访问该列表的对象。我的意思是我有一个Object objectOfList,我知道它是一个通用的值列表(例如 int 或 float 值)。我需要将项目添加到此列表中。我该怎么做?

由于我不知道通用列表的类型是什么,因此我尝试将 objectOfList 强制转换为对象列表,但它会引发异常:

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

它抛出空引用异常。

更新

它可以是int float 或任何其他类型。写代码的时候不知道是什么类型。这是从UI 中选择列表类型并创建列表的用户。

【问题讨论】:

  • 它会永远是List&lt;object&gt; 还是永远是List&lt;int&gt;List&lt;float&gt;?在这种情况下,您需要根据value 的类型进行转换,即((List&lt;int&gt;)objectOfList).Add(value);
  • @Lee 它可以是 int float 或任何其他类型。写代码的时候不知道是什么类型。这是从UI 中选择列表类型的用户,然后创建列表。
  • 是的,但它是否总是与value 完全相同的类型而不是子类型?在这种情况下,您可以根据value 的类型进行转换。如果列表元素类型是 value 的超类型,那么您可以转换为 IList

标签: c# generics generic-list


【解决方案1】:

正如 Lee 所指出的,您必须使用实际类型,而不是 object。考虑以下几点:

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

这会抛出一个NullReferenceException 但是

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

没有。

更多关于as的信息:

as 运算符类似于强制转换操作。但是,如果无法进行转换,则 as 返回 null 而不是引发异常

as (C# reference)

您还可以尝试一件事,那就是通过使用非泛型接口IList 失去List&lt;T&gt; 的泛型类型安全支持。这将允许您做您想做的事情,但如果类型不同,则会抛出 System.ArgumentException

(someList as IList).Add(1); //ok
(someList as IList).Add("hello");  //throws exception

【讨论】:

    【解决方案2】:

    列表是不变的,因此您只能将其转换回具有相同元素类型的列表,例如

    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&lt;Giraffe&gt;

    如果您不知道 value 的静态类型,那么您还必须强制转换为 IList 并准备在调用 Add 时处理异常。

    【讨论】:

      【解决方案3】:

      Object objectOfList 不能转换为 List&lt;object&gt;,因此 as 运算符返回 null。

      如果您将其初始化为List&lt;Object&gt; objectOfListObject objectOfList = new List&lt;Object&gt;();,您将不会得到空引用。例如

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

      (Example fiddle)

      【讨论】:

        【解决方案4】:

        尝试将对象列表转换回原来的样子。如果是列表,那么:

        列表 lo = ((List)objectOfList)

        这样您就可以使用列表。 然后你可以通过这个方法找出它是哪种类型的列表:

        objectOfList.ToString() 或者 objectOfList.GetType().ToString()

        【讨论】:

          猜你喜欢
          • 2020-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-25
          • 1970-01-01
          • 1970-01-01
          • 2017-06-16
          • 2021-09-23
          相关资源
          最近更新 更多