C# 接口无法实例化,那么为什么我可以在不指定具体类型的情况下使用 IEnumerable



我知道接口不能实例化,但可以创建实现接口的对象实例。

但是在这个例子中,我正在使用一个接口变量,它永远不会实例化为类的对象。

public static IEnumerable<Person> GetPeople()
{
IEnumerable<Person> people = AMethod<IEnumerable<Person>>();
return people;
}
var people = MyClass.GetPeople();
// ... operations on the people variable

因此,我绝不是指数组或列表或实现IEnumerable的另一种类型。当我调试此代码时,调试器显示 people 变量的类型为 IEnumerable。但是,如果接口不是"真实的东西",而只是一个合约,那怎么可能呢?就像在内存中一样,这是一个数组,一个列表,还是其他东西?我正在学习接口课程,但我无法解决这个问题。

AMethod<IEnumerable<Person>>()

这是调用一个看起来像这样的方法:

public  T AMethod <T> {
// Do something to create an instance of T
}

IEnumerable<Person>是传递给AMethod签名<T>的内容。这是一种通用方法。

这样做的结果是正在创建一些具体的东西(如Person[]List<Person>等)以适应接口IEnumerable<Person>。但它是由AMethod创建的,而不是您发布的任何代码。

如果你对人到底是什么类型感到好奇,不能只看AMethod,打电话Type concreteType = people.GetType();会告诉你。

IEnumerable<T>这样的抽象的有用之处在于它是由许多类实现的。

例如:

List<T>IEnumerable<T>

ImmutableArray<T>就是IEnumerable<T>

数组T[]是一个IEnumerable<T>(尽管它有点编译器的魔力,请参阅注释)。

说一个方法返回一个IEnumerable<T>只是意味着这个方法将返回实现IEnumerable的东西,你不需要关心是哪一个,但你可以依靠接口被实现的事实,从而使用foreach和linq方法在其上

如果您所需要的只是能够使用foreach枚举某些内容或应用 linq 方法,则可以隐藏实际实现(数组或列表或其他任何内容)并改用IEnumerable

一般来说,为什么要使用抽象?这是一个简短的开始答案。

想象一下,你依赖于一个特定的实现,比如List<T>,然后你把它作为List<T>参数等传递给其他函数......你的代码像这样增长。

有一天,您意识到由于某种原因(为了性能,或者因为您现在使用另一个返回某种其他类型的类的库),List<T>不是一个好的选择。

现在你需要解开依赖于这个List假设的一切。

相关内容

最新更新