类及其接口之间的引用转换
本文关键字:引用 转换 之间 接口 | 更新日期: 2023-09-27 17:57:58
我有一个实现接口的类:
public interface IMyInterface
{
string MY_VALUE { get; set; }
}
public class MyClass: IMyInterface
{
public string MY_VALUE { get; set; }
}
我正在使用列表中的类:
private List<MyClass> MyInternal;
public List<IMyInterface> MyExternal
{
get
{
return MyInternal;
}
}
这里的问题是MyInternal的类型是MyClass,所以get函数有错误。
然而,如果我先将MyInternal转换为IMyInterface,它将消除错误,但将不再有用,因为它是一个新列表,而不是原始列表:
public List<IMyInterface> MyExternal
{
get
{
return MyInternal.Select(x=>(IMyInterface)x).ToList();
}
}
我这样称呼外部属性:
MyService.MyExternal.Add(new MyClass{ MY_VALUE:"New Value" });
这将失败,因为MyExternal没有映射到MyInternal,而是映射到一个新列表。我该如何做到这一点?
即使MyClass
实现了MyInterface
,也不能将List<MyClass>
强制转换为List<MyInterface>
。
如果可以将其强制转换为List<MyInterface>
,则必须能够向其中添加任何实现MyInterface
的内容,即使它不是MyClass
。如果你可以将它强制转换为List<MyInterface>
,将该引用传递给另一个方法,该方法会"认为"它可以向该列表中添加其他内容,而实际上该列表中唯一可以包含的内容是MyClass
。我们从来没有遇到过这些场景,因为编译器阻止了它
如果你有List<MyClass>
,想要List<MyInterface>
,你可以做
var listOfMyInterface = listOfMyClass.Cast<MyInterface>().ToList();
想象一下我做了一个
public class MyClass2: IMyInterface
{
public string MY_VALUE { get; set; }
}
然后我做了
someClass.MyExternal.Add(new MyClass2())
它将不得不向private List<MyClass> MyInternal
对象添加一个MyClass2
,这是不允许的。这就是为什么你不能这么做。
为了绕过它,您必须公开一个协变接口(只允许读取列表,不允许写入,并且类型为out T
),这就是IReadOnlyList<T>
接口的用途,而List<T>
实现了该接口。
private List<MyClass> MyInternal;
public IReadOnlyList<IMyInterface> MyExternal
{
get
{
return MyInternal;
}
}
IReadOnlyCollection<T>
和IEnumerable<T>
也是可以工作的接口的其他可能的良好候选者
如果您希望MyExternal
公开的列表保持可写,您唯一的选择是更改MyInternal以使用相同类型的列表。
private List<IMyInterface> MyInternal;
public List<IMyInterface> MyExternal
{
get
{
return MyInternal;
}
}