类及其接口之间的引用转换

本文关键字:引用 转换 之间 接口 | 更新日期: 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;
    }
}