【问题标题】:in c#, how to determine the object's type when List<Object> is given?在c#中,当给定List<Object>时如何确定对象的类型?
【发布时间】:2013-03-04 15:33:12
【问题描述】:

我的方法看起来像:

Boolean actions(List<Object> input)
{
    if (input.element is String)
    {...}
    else if (input.element is PSObject)
    {...}
}

我试过input.getType().GetGenericArguments()[0] == new PSObject().GetType())

但是input.getType().GetGenericArguments()[0] 说它是对象类型...

【问题讨论】:

  • 那么当前代码和is有什么问题?在这种情况下,List&lt;X&gt; 中的泛型类型 XObject - 即编译时已知的静态类型。
  • -1(可以更正)指定适用的错误消息/指示符。

标签: c# list types covariance contravariance


【解决方案1】:

也许您的问题只是您试图使用input.element 将一个项目从列表中取出。这不是检查列表中元素类型的正确方法。

只用它来测试第一项:

bool actions(List<Object> input)
{
    var element = input.FirstOrDefault();
    if (element is String)
    {...}
    else if (element is PSObject)
    {...}
}

或者这样单独测试每个项目:

bool actions(List<Object> input)
{
    foreach (var element in input)
    {
        if (element is String)
        {...}
        else if (element is PSObject)
        {...}
    }
}

或者,如果您想确保列表的所有元素都属于给定类型,您可以使用泛型:

bool actions<T>(List<T> input)
{
    if (typeof(String).IsAssignableFrom(typeof(T))
    {...}
    else if (typeof(PSObject).IsAssignableFrom(typeof(T))
    {...}
}

【讨论】:

  • +1 眼睛好.. 这就是为什么帖子应该始终包含正确/适用的错误消息。
  • @FlyingStreudel 不,问题是 List is String 是 never true,但第一个元素可能是 String ..
  • @FlyingStreudel - 任何值类型都将被装箱在List&lt;object&gt;中。
  • 但是仅仅因为第一项是字符串并不意味着第二项不能是PSObect,所以这需要非常小心地使用。如果这是您想要的约束,那么该方法应该是通用的。
  • @Servy 是的,但没有进一步的上下文,很难给出更完整的答案。
【解决方案2】:

您必须获取列表中实例的类型,而不是列表的类型。

Boolean actions(List<Object> input) {
  foreach (object o in input) {
    if (o is String) {
      ...
    } else if (o is PSObject) {
      ...
    }
  }
}

或者,如果您知道列表中的所有对象都属于同一类型,则可以检查第一项的类型 (input[0]),然后根据该类型对所有项执行相同的操作。

【讨论】:

    【解决方案3】:

    但是 input.getType().GetGenericArguments()[0] 说它是对象类型...

    好吧,由于List&lt;T&gt; 是不变的,传入的列表的泛型参数将始终与方法参数的泛型参数完全匹配。

    在这种情况下,列表将始终objects 的列表。

    现在,列表中的每个项目都可能不是object(因为它是最派生的类型),它可以是字符串或PSObject。但是,您不能假设 所有 它们都是 object 以外的任何类型。

    因此,您可以检查列表中的特定项目是否存在更多派生类型,而不是整个列表。

    因此,您更有可能必须重构代码才能做到:

    Boolean actions(List<Object> input)
    {
        foreach(object element in input)
        {
            if (element is String)
            {...}
            else if (element is PSObject)
            {...}
        }
    }
    

    如果重要的是所有项目都属于同一类型,那么您可以使用泛型:

    Boolean actions<T>(List<T> input)
    {
        if (typeof(T) == typeof(string))
        {...}
        if(typeof(T) == typeof(PSObject))
        {...}
    }
    

    【讨论】:

    • 正如你所说List&lt;T&gt; 是不变的,不是typeof(T) 总是 typeof(object) 如果输入是List&lt;object&gt;
    • @KenKin 是的,但是由于该方法是通用的,因此您不再需要传入List&lt;object&gt;,您可以并且应该传入一个更派生类型的列表,这就是那个特定的实现。
    猜你喜欢
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2019-07-08
    • 2013-11-06
    • 2013-03-31
    • 2013-11-25
    相关资源
    最近更新 更多