使用对象的接口将对象列表转换为 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();
我在从 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();