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

21
在C#中,如果我有一个函数的参数类型为接口,那么我如何传递实现了该接口的对象?
这是一个例子:
函数的参数如下:
List<ICustomRequired>

我已经有的列表如下:

List<CustomObject> exampleList

CustomObject 继承自 ICustomRequired 接口

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

这就是我考虑完成上述任务的方式:

exampleList as List<ICustomRequired>

但是我遇到了以下错误:

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

谢谢

3个回答

21

您无法将一个类型为 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<T>实际上被定义为IEnumerable<out t>,这意味着类型参数是协变的

您能否将函数的参数更改为IEnumerable<ICustomRequired>

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

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

1

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

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

1
除了 List.Cast 之外,C# 的泛型还提供了对 协变和逆变 的良好支持。这个例子让它按照我最初想要的方式工作。
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{}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接