【问题标题】:Cannot convert type via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion无法通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换来转换类型
【发布时间】:2015-09-02 11:54:25
【问题描述】:

在C#中,如果我有一个参数类型为接口的函数的参数,如何传入实现该接口的对象。

这是一个例子:

函数的参数如下:

List<ICustomRequired>

我已有的清单如下:

List<CustomObject> exampleList

CustomObject 继承自 ICustomRequired 接口

exampleList 作为参数传递的正确语法是什么?

这就是我认为完成上述任务的方式:

exampleList as List<ICustomRequired>

但是我收到以下错误:

无法通过引用转换、装箱转换、 拆箱转换、包装转换或空类型转换

谢谢

【问题讨论】:

    标签: c# interface type-conversion


    【解决方案1】:

    您不能将一种类型的 List 强制转换为另一种类型的 List

    如果你仔细想想,你会很高兴你做不到。想象一下,如果可能的话,你可能造成的破坏:

     interface ICustomRequired
     {
     }
    
     class ImplementationOne : ICustomRequired
     {
     }
    
     class ImplementationTwo: ICustomRequired
     {
     }
    
     var listOne = new List<ImplementationOne>();
     var castReference = listOne as List<ICustomRequired>();
     // Because you did a cast, the two instances would point
     // to the same in-memory object
    
     // Now I can do this....
     castReference.Add(new ImplementationTwo());
    
     // listOne was constructed as a list of ImplementationOne objects,
     // but I just managed to insert an object of a different type
    

    但是请注意,这行代码是合法的:

     exampleList as IEnumerable<ICustomRequired>;
    

    这将是安全的,因为IEnumerable 不会为您提供任何添加新对象的方法。

    IEnumerable&lt;T&gt;实际上定义为IEnumerable&lt;out t&gt;,也就是说类型参数是Covariant

    你能把函数的参数改成IEnumerable&lt;ICustomRequired&gt;吗?

    否则,您唯一的选择就是创建一个新列表。

    var newList = (exampleList as IEnumerable<ICustomRequired>).ToList();
    

    var newList = exampleList.Cast<ICustomRequired>().ToList();
    

    【讨论】:

      【解决方案2】:

      你不能这样做,你必须转换列表

      exampleList.Cast<ICustomRequired>().ToList();
      

      【讨论】:

        【解决方案3】:

        除了List.Cast,C# 的泛型还为Covariance and contravariance 提供了良好的支持。这个例子使它以我认为你最初想要的方式工作。

        public class Program
        {
            public static void Main()
            {
                 Foo(new List<Fim>());
            }
        
            public static void Foo<T>(List<T> bar) where T : IFim
            {
                throw new NotImplementedException();
            }
        
            public class IFim{}
            public class Fim : IFim{}
        }
        

        【讨论】:

          猜你喜欢
          • 2013-07-14
          • 1970-01-01
          • 1970-01-01
          • 2012-10-27
          • 2015-04-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多