【问题标题】:Casting string to IEnumerable<object>将字符串转换为 IEnumerable<object>
【发布时间】:2015-12-22 12:30:18
【问题描述】:

我有propertyValue,这是一个传递给我的函数的对象。

我可以假设这是某种IEnumerable,但是由于接口契约,我必须将其作为object 接受,而不是直接作为IEnumerable

当我尝试将我的值转换为 IEnumerable&lt;object&gt;,以便获得长度时,我得到一个 InvalidCastException

var length = ((IEnumerable<object>) propertyValue).Cast<object>().Count();

我得到以下异常:

System.InvalidCastException:无法转换类型的对象 'System.String' 键入 'System.Collections.Generic.IEnumerable`1[System.Object]'。

【问题讨论】:

    标签: c# linq generics casting


    【解决方案1】:

    IEnumerable&lt;T&gt; 接口是协变的,但协变不适用于值类型。将值类型转换为引用类型会更改表示形式 - 需要将值装箱并返回对装箱值的引用。转换引用类型不会改变表示 - 它仍然是同一个引用,引用同一个对象。

    string 是一个IEnumerable&lt;char&gt;,因此不能转换为IEnumerable&lt;object&gt;

    正如其他答案中提到的,解决方案是强制转换为非泛型IEnumerable

    var length = ((IEnumerable) propertyValue).Cast<object>().Count();
    

    【讨论】:

      【解决方案2】:

      我已通过简单地转换为 IEnumerable 而不是转换为 IEnumerable&lt;object&gt; 来解决此问题。

      var length = ((IEnumerable) propertyValue).Cast<object>().Count();
      

      【讨论】:

      • 为什么需要使用 Cast()?
      • @VadimMartynov 使用Count() 扩展方法,该方法仅适用于通用IEnumerable&lt;T&gt;
      • @VadimMartynov 在非泛型类IEnumerable 上,Count() 没有扩展方法。要使用该方法,我必须将其转换为某种类型的IEnumerable&lt;T&gt;
      • 你不能。实际上你不应该,因为它会导致 char 类型的装箱。
      【解决方案3】:

      String 实现了IEnumerable&lt;char&gt; 接口,您可以将其强制转换为该接口

      var length = ((IEnumerable<char>) propertyValue).Count();
      

      对于未知类型的集合,您可以将其转换为 IEnumerable,然后使用您自己的 extension method 手动枚举值。

      static class EnumerableExtensions
      {
          public static int Count(this IEnumerable source)
          {
              int res = 0;
      
              foreach (var item in source)
                  res++;
      
              return res;
          }
      }
      
      var collection = propertyValue as IEnumerable;
      if(collection != null)
      {
          var length = collection.Count();
      }
      

      使用Cast() 方法会导致值类型的装箱,并且对于大集合可能会有性能问题。

      【讨论】:

      • 由于作者不知道 Enumerable 是哪种类型,所以这并不总是必要的。
      • @dryman 你是对的,这是我的失败。但是 Cast 会导致值类型的装箱。我会更新我的答案。
      【解决方案4】:

      以下代码实际上应该可以满足您的需要

      var length = (propertyValue as IEnumerable<object>).Count();      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多