使用对象的接口将对象列表转换为 IList

Casting List of objects to a IList with the interface of the object

我在从 nuget 包实现接口时遇到了一些问题。 界面中有一个属性,看起来像这样:IList<IInterfaceInstance> Implements {get;}

我的问题是从 List<InterfaceInstance> 转换为 IList<IInterfaceInstance>

这就是我想要做的,它给了我以下异常:

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var ins1 = new InterfaceInstance() {Id = "1"};
        var ins2 = new InterfaceInstance() {Id = "2"};
        List<InterfaceInstance> imps = new List<InterfaceInstance>() {ins1, ins2};
        IList<IInterfaceInstance> implements = imps as IList<IInterfaceInstance>;

        foreach( var imp in implements) {
            Console.WriteLine(imp.Id);
        }
    }

    private class InterfaceInstance : IInterfaceInstance
        {
            public string Id { get; set; }
            public string Name { get; set; }
        }

    public interface IInterfaceInstance
    {
            public string Id { get; set; }
            public string Name { get; set; }
    }
}

IList 不是 covariant,因此您不能将 List<class> 转换为 IList<interface>,并且您的 as 运算符 returns null。如果您只想遍历项目,请改用 IEnumerable<IInterfaceInstance>

您不能像那样直接转换为 IList,因为它不是协变的。否则,您可以将实现 IInterfaceInstance 但不是 InterfaceInstance 的内容添加到应该只有 InterfaceInstance 的列表中。相反,您必须像这样投射每个项目。

IList<IInterfaceInstance> implements = imps
    .Cast<IInterfaceInstance>()
    .ToList() as IList<IInterfaceInstance>;

或者您可以转换为 IEnumerable<IInterfaceInstance>,因为它是协变的,因为它只允许您拉出项目。

IEnumerable<IInterfaceInstance> implements = imps as IEnumerable<IInterfaceInstance>;

根据 documentation

The as operator explicitly converts the result of an expression to a given reference or nullable value type. If the conversion is not possible, the as operator returns null.

一般来说,泛型类型不允许其参数变化,这意味着您不能转换为不同的类型。这就是 implements 为 null 并且在尝试执行 foreach.

时失败的原因

为了实现您的意图,您必须将每个独立项目投射到 IInterfaceInstance,而不是整个列表。

您可以使用 linq 来 select 一个新的 ienumerable,传递一个 lambda 以将每个 InterfaceInstance 转换为 IInterfaceInstance:

IList<IInterfaceInstance> implements = imps.Select(interfaceInstance => (IInterfaceInstance)interfaceInstance).ToList();