Вопрос о том, как компилятор C # выдает информацию TypeRef - PullRequest
4 голосов
/ 13 апреля 2011

Я обнаружил эту интересную вещь, когда пробовал новую функцию «необязательные параметры» в C # 4.0.

Я знаю, что есть два способа использования «необязательных параметров» в C # 4.0:

static void TestMethod(int parameter = 5) { }
static void TestMethod2([Optional, DefaultParameterValue(5)]int parameter) { }

Теперь, если я скомпилирую этот код, а затем просмотрю сборку с использованием IL Dasm, то я увижу, что в окне «MetaInfo» IL Dasm есть ссылка на тип для OptionalAttribute, например:

Token:             0x01000002
ResolutionScope:   0x23000001
TypeRefName:       System.Runtime.InteropServices.OptionalAttribute
MemberRef #1 (0a000001)
-------------------------------------------------------
    Member: (0a000001) .ctor: 
    CallCnvntn: [DEFAULT]
    hasThis 
    ReturnType: Void
    No arguments.

Но признаков DefaultParameterValueAttribute нет.Это почему?

На самом деле я думаю, что эти два атрибута не должны быть здесь, потому что они обрабатываются компилятором по-разному, у них есть свои собственные значения флагов.Чтобы объяснить, что я имею в виду, взгляните на это:

    Method #2 (06000002) 
-------------------------------------------------------
    MethodName: TestMethod (06000002)
    Flags     : [Private] [Static] [HideBySig] [ReuseSlot]  (00000091)
    RVA       : 0x00002053
    ImplFlags : [IL] [Managed]  (00000000)
    CallCnvntn: [DEFAULT]
    ReturnType: Void
    1 Arguments
        Argument #1:  I4
    1 Parameters
        (1) ParamToken : (08000002) Name : parameter flags: [Optional] [HasDefault]  (00001010) Default: (I4) 5

Method #3 (06000003) 
-------------------------------------------------------
    MethodName: TestMethod2 (06000003)
    Flags     : [Private] [Static] [HideBySig] [ReuseSlot]  (00000091)
    RVA       : 0x00002056
    ImplFlags : [IL] [Managed]  (00000000)
    CallCnvntn: [DEFAULT]
    ReturnType: Void
    1 Arguments
        Argument #1:  I4
    1 Parameters
        (1) ParamToken : (08000003) Name : parameter flags: [Optional] [HasDefault]  (00001010) Default: (I4) 5

Это метаданные двух методов.Мы видим, что в последней строке каждого раздела кода уже сохранено значение параметра по умолчанию, так почему же на OptionalAttribute все еще ссылаются?

1 Ответ

3 голосов
/ 13 апреля 2011

Это можно считать ошибкой в ​​компиляторе. Если вы внимательно изучите сборку, то ничего не будет ссылаться на OptionalAttribute TypeRef.

TypeRef не будет присутствовать в результирующей сборке, если вы явно не добавите в нее TestMethod2. Это просто показывает, что атрибут добавляется в первый проход, а затем удаляется. И это также показывает, что DefaultParameterValueAttribute обрабатывается компилятором по-разному.

В конечном счете, это действительно небольшая деталь реализации, например, компилятор Mono C # не будет создавать TypeRef для любого атрибута в результирующей сборке.

...