Как работают дополнительные параметры VB.NET "Под капотом"? Являются ли они CLS-совместимыми?
Скажем, у нас есть следующее объявление метода:
Public Function MyMethod(ByVal param1 As Integer, _
Optional ByVal param2 As Integer = 0, _
Optional ByVal param3 As Integer = 1) As Integer
Return param1 + param2 + param3
End Function
Как VB.NET делает необязательные параметры работы в пределах CLR? Являются ли дополнительные параметры CLS-совместимыми?
Ответы
Ответ 1
Интересно, что это декомпилированный код С#, полученный с помощью отражателя.
public int MyMethod(int param1,
[Optional, DefaultParameterValue(0)] int param2,
[Optional, DefaultParameterValue(1)] int param3)
{
return ((param1 + param2) + param3);
}
Обратите внимание на атрибуты Optional и DefaultParameterValue. Попробуйте поместить их в методы С#. Вы обнаружите, что вам по-прежнему требуется передать значения методу. Однако в коде VB он превратился в Default! При этом я лично никогда не использовал Default даже в коде VB. Это похоже на хак. Перегрузка метода делает трюк для меня.
По умолчанию действительно помогает справиться с Excel Interop, что является болью в заднице, чтобы использовать прямо из коробки на С#.
Ответ 2
Вопреки распространенному мнению, необязательные параметры выглядят как CLS-совместимые. (Тем не менее, моя основная проверка для этого заключалась в том, чтобы пометить сборку, класс и метод всеми атрибутами CLSCompliant, установленными в True.)
Итак, как это выглядит в MSIL?
.method public static int32 MyMethod(int32 param1,
[opt] int32 param2,
[opt] int32 param3) cil managed
{
.custom instance void [mscorlib]System.CLSCompliantAttribute::.ctor(bool) = ( 01 00 01 00 00 )
.param [2] = int32(0x00000000)
.param [3] = int32(0x00000001)
// Code size 11 (0xb)
.maxstack 2
.locals init ([0] int32 MyMethod)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add.ovf
IL_0004: ldarg.2
IL_0005: add.ovf
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000a: ret
} // end of method Module1::MyMethod
Обратите внимание на отметки [opt] по параметрам - MSIL поддерживает это самостоятельно, без каких-либо взломов. (В отличие от поддержки MSIL для ключевого слова VB Static, что является совсем другой темой.)
Итак, почему в С# нет? Я не могу ответить на это, кроме моих предположений, что это может быть предполагаемый недостаток спроса. Мое предпочтение всегда заключалось в том, чтобы указать параметры, даже если они были необязательными - для меня код выглядит более чистым и его легче читать. (Если есть пропущенные параметры, я часто смотрю сначала на перегрузку, которая соответствует видимой сигнатуре - это только после того, как я не смогу найти тот, который я понимаю, что задействованы дополнительные параметры.)