将对象传递给实现特定接口的函数是否有成本,而函数只接受该接口?像:C#接口问题
Change (IEnumerable<T> collection)
和我通:
List<T>
LinkedList<T>
CustomCollection<T>
使所有这些实现IEnumerable。但是当你将其中的任何一个传递给Change方法时,它们是否会转换为IEnumerable,因此存在投射成本,但也会失去其独特方法等问题?
将对象传递给实现特定接口的函数是否有成本,而函数只接受该接口?像:C#接口问题
Change (IEnumerable<T> collection)
和我通:
List<T>
LinkedList<T>
CustomCollection<T>
使所有这些实现IEnumerable。但是当你将其中的任何一个传递给Change方法时,它们是否会转换为IEnumerable,因此存在投射成本,但也会失去其独特方法等问题?
不,没有铸造涉及List<T>
IS-A
IEnumerable<T>
。这是使用不需要投射的多态性。
编辑:下面是一个例子:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
foo(new List<int>());
}
static void foo(IEnumerable<int> list) { }
}
为Main
的IL是:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 8
L_0000: nop
L_0001: newobj instance void [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
L_0006: call void Program::foo(class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>)
L_000b: nop
L_000c: ret
}
正如你可以看到有没有参与铸造。将List<T>
的实例推入堆栈,并在之后立即调用foo
。
加上对象不会“丢失”他们的方法,它们只是在函数内部不可用。这是可以的,因为该方法仅期望IEnumerable
我不相信会有成本。由于这些类型已经实现了IEnumerable,因此该对象应该可以立即使用(请注意,这主要是一种猜测;我不知道CLR的vtables是如何在幕后真正起作用的)。
如果是有成本的,这将是令人惊讶这么小,如果它的确与众不同,你可能不应该使用CLR开始。
+1非常有趣的问题! – 2009-02-27 17:32:45