【问题标题】:Casting List of objects to a IList with the interface of the object使用对象的接口将对象列表转换为 IList
【发布时间】:2019-12-12 17:20:30
【问题描述】:

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

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

这就是我正在尝试做的事情,它给了我以下异常:

未处理的异常。 System.NullReferenceException:对象引用未设置为对象的实例。

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 不是协变的,所以你不能像那样转换泛型类型。您可以将其转换为IEnumerable&lt;IItnerfaceInstance&gt;,因为您只能从IEnumerable 中获取项目。否则,您需要强制转换每个项目才能使其正常工作。

标签: c# .net interface casting instance


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    根据documentation

    as 运算符将表达式的结果显式转换为 给定的引用或可为空的值类型。如果转换不 可能,as 运算符返回 null。

    一般来说,泛型类型不允许其参数变化,这意味着您不能强制转换为不同的类型。这就是为什么implements 为空并且在尝试执行foreach 时失败的原因。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        或者,您可以转换为 IEnumerable&lt;IInterfaceInstance&gt;,因为它是协变的,因为它只允许您将项目拉出。

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

        【讨论】:

          猜你喜欢
          • 2011-01-01
          • 1970-01-01
          • 2011-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-24
          相关资源
          最近更新 更多