2017-01-20 7 views
4

Я специально обращаю внимание на нулевое распространение, поскольку оно относится к bool? и использованию метода возврата bool. Например, рассмотрим следующее:Почему нулевое распространение неуклонно распространяется Nullable <T>?

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any(); 
} 

Это не компилируется, и следующая ошибка существует:

Не удается неявно преобразовать логическое значение? обмануть. Явное преобразование существует (вы пропускаете приведение)?

Это означает, что он обрабатывает все тело метода как bool?, как таковой, я предположил бы, что я мог бы сказать .GetValueOrDefault() после .Any(), но это не допускается, как .Any() возвращается bool не bool?.

Я знаю, что я мог бы сделать одно из следующих действий, как работа вокруг:

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any() 
     ?? false; 
} 

Или

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    var any = 
     property?.AttributeProvider 
       .GetAttributes(typeof(TAttribute), false) 
       .Any(); 

    return any.GetValueOrDefault(); 
} 

Или

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any() 
     ?? false; 
} 

Мой вопрос, почему я не могу непосредственно вызывать .GetValueOrDefault() цепочку на вызове .Any()?

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return (property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any()) 
        .GetValueOrDefault(); 
} 

Я думаю, что это будет иметь смысл, поскольку значение фактически bool? в данный момент и не bool.

+1

Вы должны поставить скобки, так '.' оператор известно, где состояние вызова цепи end: '(свойство? .AttributeProvider.GetAttributes (typeof (TAttribute), false) .Any()). GetValueOrDefault()'. – PetSerAl

+0

Если 'property' равно null, тогда метод попытается вернуть null. Однако это не может быть вызвано тем, что тип возвращаемого значения - 'bool', который не является типом с нулевым значением. Измените тип возврата на 'bool?'. – Abion47

ответ

5

После того, как оператор ?. выполнил следующую цепочку вызовов, интерпретируется как условный не только немедленный вызов. Таким образом, этот код:

property?.AttributeProvider 
     .GetAttributes(typeof(TAttribute), false) 
     .Any() 

истолковано как

property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any() 

Если добавить GetValueOrDefault():

property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any() 
             .GetValueOrDefault() 

он потерпит неудачу, потому что Any() возвращение bool не bool?.Таким образом, вы должны использовать круглые скобки здесь:

(property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any()) 
             .GetValueOrDefault() 

же скобку вам нужно использовать, когда вы используете ?. оператор:?

(property?.AttributeProvider 
      .GetAttributes(typeof(TAttribute), false) 
      .Any()) 
      .GetValueOrDefault() 
2

Выполняется звонок по вызову Any(), который возвращает bool. Если вы хотите выполнить результат по всему телу, вам придется заключить его в круглые скобки.

return (property?.AttributeProvider 
       .GetAttributes(typeof(TAttribute), false) 
       .Any()) 
       .GetValueOrDefault(); 

Нулевая условный оператор короткий оператор замыкания и при этом ничего справа от точки, которая пытается выполнить на объекте или каких-либо его свойств или методов не будет выполняться, если объект является недействительным. Итак, чтобы выполнить код в целом, вы должны его каким-то образом обернуть (круглые скобки или другой объект).

+0

Я знаю, что я могу в скобки. Но это не то, о чем я прошу. C# обрабатывает весь оператор как «bool?», Но я не могу воздействовать на него так, как будто это «bool?». Я знаю, что он делает, я спрашиваю, почему. –