The analyzer has detected a potential error that can result in a null dereference. The result of applying the conditional access operator to a potentially null element is enclosed in parentheses before further dereference.
This means one of the two scenarios:
1) An error will occur if the object being accessed is an empty reference.
2) The expression always evaluates correctly because the object the conditional access operator is applied to is never equal to null. In this case, the check is unnecessary.
Consider the following example. Executing this code may lead to throwing an exception:
var t = (obj?.ToString()).GetHashCode();
If 'obj' happens to have the value null, the 'ToString()' method of the 'obj?.ToString()' expression will not be called – this is how the conditional access operator works. However, the call to the 'GetHashCode()' method will be executed anyway because it is not affected by the conditional access operator.
var t = obj?.ToString().GetHashCode();
We have not only eliminated the unsafe dereference but also made sure that the 't' variable is of type 'Nullable<int>', which correctly represents its contents as potentially null.
The next example demonstrates a case where the dereference is safe and the check is not needed:
object obj = GetNotNullString(); .... var t = ((obj as String)?.Length).GetHashCode();
This expression evaluates correctly every time. The 'obj' object is always of type 'String', which means the check following the conversion is redundant.
var t = ((String)obj).Length.GetHashCode();
This diagnostic is classified as: