Version Used:
Branch master (23 Dec 2019)
Latest commit 8614121 by Charles Stoner:
Do not include binding cache in BoundLambda (#40534)
Steps to Reproduce:
Compile the following code:
#nullable enable
using System.Collections.Generic;
class Base
{
public bool Equals(string? x, string? y) => true;
public int GetHashCode(string x) => 0;
}
class Quasi : Base, IEqualityComparer<string>
{
void M(string? s)
{
if (Equals(s, null)) return;
s.ToString();
}
}
Expected Behavior:
No warnings. s is compared to null via IEqualityComparer<string>.Equals and the method does not dereference it in such cases.
Actual Behavior:
warning CS8602: Dereference of a possibly null reference. is reported for s.ToString()
Notes
If you provide an implementation of Equals in Quasi instead of quasi-implementing it via the Equals method in Base the warning goes away so it seems that Roslyn just doesn't check quasi-implementations when checking for well-known equality methods in NullableWalker.LearnFromEqualsMethod.isWellKnownEqualityMethodOrImplementation which seems to be a bug.
i.e. there's no such warning in the following code:
#nullable enable
using System.Collections.Generic;
class Base
{
public int GetHashCode(string x) => 0;
}
class Quasi : Base, IEqualityComparer<string>
{
public bool Equals(string? x, string? y) => true;
void M(string? s)
{
if (Equals(s, null)) return;
s.ToString();
}
}
As mentioned above the same problem exists with other well-known interfaces' metods e.g. IEqutable.Equals. The following code snippet does not produce any warnings for dereferencing s despite it being explicitly compared to null. It will report the warning correctly if you move the Equals(Quasi? x) method from Base to Quasi:
#nullable enable
using System;
class Base
{
public bool Equals(Quasi? y) => true;
}
class Quasi : Base, IEquatable<Quasi>
{
void M(Quasi s)
{
if (s.Equals(null))
{
s.ToString();
}
}
}
Version Used:
Steps to Reproduce:
Compile the following code:
Expected Behavior:
No warnings.
sis compared tonullviaIEqualityComparer<string>.Equalsand the method does not dereference it in such cases.Actual Behavior:
warning CS8602: Dereference of a possibly null reference.is reported fors.ToString()Notes
If you provide an implementation of
EqualsinQuasiinstead of quasi-implementing it via theEqualsmethod inBasethe warning goes away so it seems that Roslyn just doesn't check quasi-implementations when checking for well-known equality methods inNullableWalker.LearnFromEqualsMethod.isWellKnownEqualityMethodOrImplementationwhich seems to be a bug.i.e. there's no such warning in the following code:
As mentioned above the same problem exists with other well-known interfaces' metods e.g.
IEqutable.Equals. The following code snippet does not produce any warnings for dereferencingsdespite it being explicitly compared tonull. It will report the warning correctly if you move theEquals(Quasi? x)method fromBasetoQuasi: