【问题标题】:How to check if a variable is an IEnumerable of some sort如何检查变量是否是某种 IEnumerable
【发布时间】:2011-01-04 03:19:02
【问题描述】:

基本上我正在构建一个非常通用的 T4 模板,我需要它做的一件事就是打印variable.ToString()。但是,我希望它评估列表并通过它们进行遍历,而不是打印 ListItem.ToString() 我的 T4 模板不知道 variable 将提前是什么类型,这就是为什么它如此通用。

但我当前生成的代码如下所示:

if(variable!=null)
  if(variable is IEnumerable) //error here
    foreach(var item in variable)
      Write(item.ToString());

我在“使用泛型类型 System.Generic.Collections.IEnumerable 需要一个类型参数”的标记行上收到编译器错误

我实际上并不关心它是什么类型,我只是想知道您是否可以通过变量进行 foreach。我应该改用什么代码?

【问题讨论】:

    标签: c# generics foreach ienumerable


    【解决方案1】:

    但是,您已经接受了答案,因为通用 IEnumerable<T> 实现了非通用 IEnumerable,您可以直接转换为。

    // Does write handle null? Might need some sanity aswell.
    
    var enumerable = variable as System.Collections.IEnumerable; 
    
    if (enumerable != null)
        foreach(var item in enumerable)
             Write(item);
    else
        Write(item);     
    

    【讨论】:

    • 这看起来实际上可能是更好的答案。
    • 我改变了答案,因为我最终使用了这种方法,在我看来它更干净。
    • 另外,为了解决下面提到的 Mono 错误,我必须先将 variable 转换为 object
    • @Earlz:这与您原来的if (variable is IEnumerable) 测试有何不同?如果您想测试IEnumerable,那么假设您的源代码顶部有正确的using 指令,那么这对您来说应该很好。
    • 请记住 String : IEnumerable 。这可能会产生一些意想不到的结果。
    【解决方案2】:

    如果您想测试非泛型 IEnumerable,则需要在源文件顶部包含 using System.Collections 指令。

    如果你想测试某种IEnumerable<T>,那么你需要这样的东西:

    if (variable != null)
    {
        if (variable.GetType().GetInterfaces().Any(
                i => i.IsGenericType &&
                i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
        {
            // foreach...
        }
    }
    

    【讨论】:

    • @Earlz System.Collections.Generic != System.Collections -- 帖子中的错误表示未找到非泛型 (IEnumerable) 类型。
    • 嘿,我用过这个,Mono 打了我一巴掌Invalid IL code in EViewEngine.TestView:BuildOutput (): IL_0105: castclass 0x1b000002 嗯,这很有趣。
    • foreach 出现错误:foreach(var item in (IEnumerable&lt;object&gt;)v) __Output.Append(item.ToString()) 看起来我有错误要报告。
    【解决方案3】:

    其他答案已经指出了通用/非通用 IEnumerable 的区别,但我还应该指出,您还需要专门测试 String ,因为它实现了 IEnumerable 但我怀疑您是否希望将其视为一个集合字符数。

    【讨论】:

      【解决方案4】:

      从 C# 7.0 开始,您也可以这样实现:

      if (variable is IEnumerable enumVar)
      {
          foreach (var e in enumVar)
          {
              ...
          }
      }
      

      【讨论】:

        【解决方案5】:

        嗯,有点简单,但是......如果你只有:

        using System.Collections.Generic;
        

        您可能需要添加:

        using System.Collections;
        

        前者定义IEnumerable&lt;T&gt;,后者定义IEnumerable

        【讨论】:

          【解决方案6】:

          general中,没有非泛型基类型/接口,这需要GetType 和通过基类型/接口的递归查找。

          然而,这里不适用 :-) 只需使用继承自 generic IEnumerable (System.Collections.Generic.IEnumerable&lt;T&gt;) 的 non-generic IEnumerable (System.Collections.IEnumerable)。

          【讨论】:

            【解决方案7】:

            您实际上可以直接测试任何泛型类型的基类。

            instance.GetGenericTypeDefinition()  == typeof(IEnumerable<>)
            

            【讨论】:

              【解决方案8】:

              如果您不关心对象类型并且您不在 C# 7.0+ 中的通用方法中

                      if (item is IEnumerable<object> enumVar)
                      {
                          foreach (var e in enumVar)
                          {
                                  e.ToString();
              
                          }
                      }
              

              在 C# 中

                      if (item is IEnumerable<object>)
                      {
                          var enumVar = item as IEnumerable<object>;
                          foreach (var e in enumVar)
                          {
                              e.ToString();
              
                          }
                          //or you can cast an array to set values, 
                          //since IEnumerable won't let you, unless you cast to IList :) 
                          //but array version here 
                          //https://stackoverflow.com/a/9783253/1818723
                      }
              

              【讨论】:

                【解决方案9】:

                这是一个老问题,但我想展示另一种方法来确定 SomeType 是否为 IEnumerable

                var isEnumerable = (typeof(SomeType).Name == "IEnumerable`1");
                

                【讨论】:

                • 这行不通,因为任何特定类型的可枚举都不会像那样。例如,List 的名称应类似于“List`1”。此外,这个数字并不总是 1,所以你也不能假设。
                猜你喜欢
                • 1970-01-01
                • 2016-04-29
                • 2011-09-10
                • 2011-09-07
                • 1970-01-01
                • 2011-09-28
                • 2012-06-21
                • 2011-07-13
                • 1970-01-01
                相关资源
                最近更新 更多