2017-01-29 12 views
1

Любой может это объяснить?Использование равных в общем методе

void Main() 
{ 
    int a = 1; 
    short b = 1; 

    Console.WriteLine(b.Equals(a));  // false 
    Console.WriteLine(a.Equals(b));  // true 

    Test<int, short>(a, b); // prints: false, false 
    Test(a, b);    // prints: false, false 
} 

void Test<T1, T2>(T1 x, T2 y) 
{ 
    Console.WriteLine(y.Equals(x)); 
    Console.WriteLine(x.Equals(y)); 
} 

(не позволит мне писать без добавления еще какой-нибудь текста, так что вот еще немного ...)

+0

Также смотрите: [Когда общий тип разрешен в C#?] (Http://stackoverflow.com/questions/17734247/when-is-the-generic-type-resolved-in-c) – Costas

+0

и это [почему этот родовой не разрешен во время компиляции?] (http://stackoverflow.com/questions/6127855/why-is-this-generic-not-resolved-at-compile-time) – Costas

+0

Глядя на IL, код в общем методе всегда помещается в коробку, а код в «основном» методе - нет. – Costas

ответ

3

ваших трех вызовов вернуться false, потому что они называют Object.Equals(Object).

Вы сравниваете коробку Int32 с коробкой Int16 (short), поэтому они являются двумя неравными объектами и возвращают false. overrides из Equals(Object) сначала проверьте, что объект в коробке, который они получают, имеет тот же точный тип, который Int16 не является.

a.Equals(b) вызывает Int32.Equals(Int32), неявно преобразуя b в Int32 во время компиляции. Следовательно, этот метод видит два Int32 s с тем же значением и возвращает true.

2

Ил показывает это: Первый звонок в штучной упаковке:

IL_0000: nop   
IL_0001: ldc.i4.1  
IL_0002: stloc.0  // a 
IL_0003: ldc.i4.1  
IL_0004: stloc.1  // b 
IL_0005: ldloca.s 01 // b 
IL_0007: ldloc.0  // a 
IL_0008: box   System.Int32 
IL_000D: call  System.Int16.Equals 
IL_0012: call  System.Console.WriteLine 
IL_0017: nop   
IL_0018: ret   

Второе: не

IL_0000: nop   
IL_0001: ldc.i4.1  
IL_0002: stloc.0  // a 
IL_0003: ldc.i4.1  
IL_0004: stloc.1  // b 
IL_0005: ldloca.s 00 // a 
IL_0007: ldloc.1  // b 
IL_0008: call  System.Int32.Equals 
IL_000D: call  System.Console.WriteLine 
IL_0012: nop   
IL_0013: ret 

Ил генерируется для универсального метода всегда бокс:

Test<T1,T2>: 
IL_0000: nop   
IL_0001: ldarga.s 02 
IL_0003: ldarg.1  
IL_0004: box   T1 
IL_0009: constrained. T2 
IL_000F: callvirt System.Object.Equals 
IL_0014: call  System.Console.WriteLine 
IL_0019: nop   
IL_001A: ldarga.s 01 
IL_001C: ldarg.2  
IL_001D: box   T2 
IL_0022: constrained. T1 
IL_0028: callvirt System.Object.Equals 
IL_002D: call  System.Console.WriteLine 
IL_0032: nop   
IL_0033: ret 

и звонок по этому методу:

IL_0000: nop   
IL_0001: ldc.i4.1  
IL_0002: stloc.0  // a 
IL_0003: ldc.i4.1  
IL_0004: stloc.1  // b 
IL_0005: ldarg.0  
IL_0006: ldloc.0  // a 
IL_0007: ldloc.1  // b 
IL_0008: call  Test<Int32,Int16> 
IL_000D: nop   
IL_000E: ret 

поэтому, даже когда тип известен во время компиляции, значения по-прежнему будут вставлены в коробку.