Inexplicable CS8978 'T' cannot be made nullable
See original GitHub issueVersion Used: Visual Studio 2022, .NET 6.0
Steps to Reproduce:
Create a new C# library in Visual Studio 2022. Add this class:
public sealed class Element<T>
{
public Element(T key)
{
Key = key;
}
public T Key { get; }
public Element<T>? Next { get; set; }
public readonly static IEqualityComparer<Element<T>> Comparer = new ElementSnapshotComparer();
public class ElementSnapshotComparer : IEqualityComparer<Element<T>>
{
public bool Equals(Element<T>? x, Element<T>? y)
{
return Equals(x?.Key, y is null ? null : y.Key) && Equals(x?.Next, y?.Next);
}
public int GetHashCode([DisallowNull] Element<T> obj)
{
return HashCode.Combine(obj.Key, obj.Next);
}
}
}
Expected Behavior:
The code compiles.
Actual Behavior:
The code doesn’t compile. Instead, it fails to compile with this error message:
Error CS8978 ‘T’ cannot be made nullable.
The offending expression is x?.Key, even though it was suggested by Visual Studio.
Notice the alternative null check made for y: y is null ? null : y.Key, which does compile. I left the two alternative versions side by side to be able to talk about the different compiler behaviour.
For the y is null ? null : y.Key expression, Visual Studio helpfully suggests IDE0031 Null check can be simplified, which, if followed, refactors the expression to y?.Key, which then also fails to compile.
I’ve tried to search for CS8978, but haven’t found anything that looks relevant. While I’m aware of #59805, it doesn’t look like the same issue to me.
It’s possible that this is correct behaviour, and that I’m just too ignorant to understand that this is so. If so, however, may I suggest a more helpful error message? (I have 20 years of C# experience, so if this confuses me, it may confuse other people, too.)
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:7 (3 by maintainers)
Top Related StackOverflow Question
Two reactions to that:
T ~ int, so that is not a useful option.xandy, above, are not of the typeT. They are of the typeElement<T>, which is literally a class. If “The compiler is worried about T being a struct.”, I have to admit that I understand nothing. Why is that even relevant?Thanks. Def an issue for IDE side to fix.