Разница между ParameterInfo.IsOptional и ParameterInfo.HasDefaultValue?
Они оба звучат одинаково. Из MSDN:
Получает значение, указывающее, является ли этот параметр необязательным.
Этот метод зависит от необязательного флага метаданных. Этот флаг может быть вставлен компиляторами, но компиляторы не обязаны это делать.
Этот метод использует опциональный флаг перечислителя ParameterAttributes.
ParameterInfo.HasDefaultValue (новое в.NET 4.5)
Получает значение, указывающее, имеет ли этот параметр значение по умолчанию.
Разве они не одинаковы? Я сделал быстрый тест:
public void A(string value)
{
}
public void B(string value, int i = -1)
{
}
Я написал:
var a = AInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray();
var b = AInfo.GetParameters().Select(p => p.IsOptional).ToArray();
var c = BInfo.GetParameters().Select(p => p.HasDefaultValue).ToArray();
var d = BInfo.GetParameters().Select(p => p.IsOptional).ToArray();
//a equals b; and c equals d
Так в каком контексте они отличаются? Почему BCL ввел HasDefaultValue
в.NET 4.5 недавно?
3 ответа
Если мы посмотрим на реализацию IsOptional
посмотрим:
public bool IsOptional
{
[__DynamicallyInvokable] get
{
return (this.Attributes & ParameterAttributes.Optional) != ParameterAttributes.None;
}
}
Это зависит от флага метаданных, но как написано в msdn:
Этот метод зависит от необязательного флага метаданных. Этот флаг может быть вставлен компиляторами, но компиляторы не обязаны это делать.
Это означает, что это зависит от компилятора, и если мы используем другой компилятор, мы можем получить тот параметр, который имеет значение по умолчанию, не будет иметь IsOptional
флаг. Теперь давайте посмотрим, как реализовано свойство HasDefaultValue:
public override bool HasDefaultValue
{
get
{
if (this.m_noMetadata || this.m_noDefaultValue)
return false;
else
return this.GetDefaultValueInternal(false) != DBNull.Value;
}
}
Он всегда проверяет, имеет ли параметр значение по умолчанию и не зависит от компилятора. Это может быть не на 100% правильный ответ, просто мои мысли.
ОБНОВЛЕНИЕ 0
Вот пример, где параметр имеет не значение по умолчанию, но IsOptional
правда:
public static void Method([Optional]string parameter)
{
}
ParameterInfo parameterInfo = typeof(Program).GetMethod("Method").GetParameters()[0];
//Is true
bool isOptional = parameterInfo.IsOptional;
//Is false
bool hasDefaultValue = parameterInfo.HasDefaultValue;
Дэнни Чен и vvs0205 утверждают, что разница IsOptional
всегда зависит от компилятора, и для проверки, является ли параметр необязательным параметром, для которого задано значение по умолчанию, используйте HasDefaultValue
,
bool isOptional = parameterInfo.IsOptional;
bool isOptionalWithADefaultValue = parameterInfo.HasDefaultValue; //.NET 4.5
bool isOptionalWithADefaultValue = (p.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault; //.NET 4 and below
Взято отсюда (воспользуйтесь другими недокументированными приемами, чтобы получить то же самое в этой теме)
Вы не можете получить заключение "они одинаковы", используя "a равно b; а c равно d", например:
int[] a = new[] { 0, 1, 5 };
var c = a.Where(n => n < 2).ToArray();
var d = a.Where(n => n < 3).ToArray();
//you can't say "2 == 3" even c equals to d in sequence
Хорошо, вернемся к теме, в настоящее время необязательный параметр всегда имеет значение по умолчанию, этот вывод верен "на данный момент". Но AFAIK это недокументированное поведение, что означает, что компилятор может изменить свое поведение / реализацию на необязательные параметры. Поэтому, если вы хотите проверить (через отражение), является ли параметр необязательным, используйте .IsOptional
имущество. Если вы хотите проверить, имеет ли оно значение по умолчанию (может быть отмечено каким-либо атрибутом, например DefaultValue? Просто возможно), используйте .HasDefaultValue
имущество. Звучит как лишние слова, но это правда.