类似的扩展方法——有什么区别吗?
Similar Extension methods - are there any differences?
这两种扩展方式有什么区别?
public static class Test
{
public static int First<T>(this T obj)
{
return 2;
}
public static int Second(this object obj)
{
return 2;
}
}
有一些不同,是的。第一个不会装箱值类型 - 但最终会针对不同类型的参数多次 JIT 编译方法(所有引用类型一次,每个值类型一次)。
所以:
byte x1 = 10;
int y1 = x1.First(); // No boxing
byte x2 = 10;
int y2 = x2.Second(); // Boxes before the call
生成的 IL 是:
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: call int32 Test::First<uint8>(!!0)
IL_000a: stloc.1
IL_000b: ldc.i4.s 10
IL_000d: stloc.2
IL_000e: ldloc.2
IL_000f: box [mscorlib]System.Byte
IL_0014: call int32 Test::Second(object)
此外,在您的 First
扩展方法中,您可以获得 编译时 类型的 T
与 执行分开-time obj
引用的对象的类型。因此,例如,更改方法的主体:
public static class Test
{
public static int First<T>(this T obj)
{
Console.WriteLine("Compile-time type: {0}", typeof(T));
Console.WriteLine("Execution-time type: {0}", obj.GetType());
return 2;
}
public static int Second(this object obj)
{
// No compile-time type to know about
Console.WriteLine("Execution-time type: {0}", obj.GetType());
return 2;
}
}
然后:
Stream foo = new MemoryStream();
foo.First(); // Will print Stream, then MemoryStream
foo.Second(); // Only knows about MemoryStream
这两种扩展方式有什么区别?
public static class Test
{
public static int First<T>(this T obj)
{
return 2;
}
public static int Second(this object obj)
{
return 2;
}
}
有一些不同,是的。第一个不会装箱值类型 - 但最终会针对不同类型的参数多次 JIT 编译方法(所有引用类型一次,每个值类型一次)。
所以:
byte x1 = 10;
int y1 = x1.First(); // No boxing
byte x2 = 10;
int y2 = x2.Second(); // Boxes before the call
生成的 IL 是:
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: call int32 Test::First<uint8>(!!0)
IL_000a: stloc.1
IL_000b: ldc.i4.s 10
IL_000d: stloc.2
IL_000e: ldloc.2
IL_000f: box [mscorlib]System.Byte
IL_0014: call int32 Test::Second(object)
此外,在您的 First
扩展方法中,您可以获得 编译时 类型的 T
与 执行分开-time obj
引用的对象的类型。因此,例如,更改方法的主体:
public static class Test
{
public static int First<T>(this T obj)
{
Console.WriteLine("Compile-time type: {0}", typeof(T));
Console.WriteLine("Execution-time type: {0}", obj.GetType());
return 2;
}
public static int Second(this object obj)
{
// No compile-time type to know about
Console.WriteLine("Execution-time type: {0}", obj.GetType());
return 2;
}
}
然后:
Stream foo = new MemoryStream();
foo.First(); // Will print Stream, then MemoryStream
foo.Second(); // Only knows about MemoryStream