2015-12-16 5 views
5
.method public static void Test<class T>(object A_0) cil managed 
{ 
    // Code size  13 (0xd) 
    .maxstack 1 
    .locals init (!!T V_0) 
    IL_0000: ldarg.0 
    IL_0001: isinst  !!T 
    IL_0006: unbox.any !!T 
    IL_000b: stloc.0 
    IL_000c: ret 
} // end of method DemoType::Test 

Равное C# код:CIL unbox_any инструкция - странное поведение

public static void Test<T>(object o) where T : class 
{ 
    T t = o as T; 
} 

Мои вопросы:

  1. Почему unbox.any называют? если вы просто делаете

    var a = father as child 
    

    isinst intruction не позвонит и не unbox.any, и если я удалю общее определение и я буду стараться не бросать (isinst) объекта к некоторому классу, не unbox.any будет вызываться.

  2. Возможно, unbox.any был вызван из-за общего определения, поэтому в этом случае unbox.any необходимо выбросить исключение NullReferenceException, потому что ответ инструкции isinst возвращает null для этого каста. см. unbox_any. И если вы попытаетесь запустить этот код, вы увидите, что исключение не было выбрано.

Update

Я могу понять unbox_any becuase параметра типа объекта и попытаться привести его к конкретному типу после проверки isinst. Возможно, дженерики тоже влияют.

Мой вопрос: почему бы не выбрасывать исключение в unbox.any, если объект obj, который мы пытаемся удалить в T, равен нулю?

В документации говорится: «Исключение NullReferenceException выбрано, если obj является нулевой ссылкой».

+0

Можете ли вы рассказать о том, что так странно? Для меня это имеет смысл. В пункте (2) вы также не задавали вопрос. – usr

+0

@usr Сначала я хочу проверить, почему были вызваны unbox_any. Какой смысл называть их обоих? (isinst и unbox_any) Во-вторых, и что более важно, почему исключение не возникает, если obj передано unbox_any, равно null? –

ответ

4

Unbox должен поддерживать верификатора. Верификатор не особенно сообразителен, зная, что параметр типа T всегда будет ссылочным типом, поэтому компилятор C# испускает ненужные ненужные ненужные файлы.

Если вы выполните поиск исходного кода Roslyn для Unbox_any и IsVerifierReference, вы увидите, что это происходит в нескольких местах вокруг генератора кода.

Дрожание будет знать при генерации кода, является ли параметр типа ссылкой или нет, и должен генерировать достойный код независимо от кажущейся ненужной инструкции.

+1

Если кто-то заинтересован в этом, я рекомендую посмотреть [здесь] (http://stackoverflow.com/questions/34382683/jitter-logic-to-remove-unbox-any?lq=1) для полной картины –