C# Type 字符串的种类?是 TypeKind.Class

C# TypeKind of string? is TypeKind.Class

改写问题: 我有这个 equalitycomparer 与 Generic type constrained to a class

public class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class
{
    public static ReferenceEqualityComparer<T> Default => new();

    public bool Equals(T? x, T? y) => ReferenceEquals(x, y);

    public int GetHashCode(T? obj) => RuntimeHelpers.GetHashCode(obj);
}

当 class 假设

public class A
{
   public string? P1{get; set;}
}

被代码生成器消耗

[Generator]
public class MyCodeGenerator : ISourceGenerator
{
}

NetAnalyzer 表示 string? 的 TypeKind 为 class

但是当我这样做时,

#nullable enable        
[TestMethod]
public void RefTest()
{
    string? s1 = "adsad";
    string? s3 = s1;
    Assert.IsTrue(ReferenceEqualityComparer<string?>.Default.Equals(s1, s3));
}
#nullable restore

它说 string? 不匹配 'class' 约束。即使分析器告诉我它是 class,我是否遗漏了什么?还是我误解了这个概念?

原问题:根据微软文档Nullable的描述,他们class化为structs,但为什么是CodeAnalyzer 告诉我 string? 的 TypeKind 是 TypeKind.Class?

这里有一些上下文,在我正在编写的库中,classes 被分析用于源代码生成(C# 9 源代码生成器),它本质上是使用 .NetAnalyzer。 class 的每个属性都将检查它们的类型是否被视为 class。结果 string? 被认为是 Class.

strings are classes and cannot be used as generic type argument for Nullable because of the generic constraint where T : struct. In your context string? is a nullable reference type,可用于向编译器指示引用类型不应将 null 作为值(变量仍然可以将 null 作为值并应进行检查对于 public API 中的 null 值,但当您在不可空上下文中使用 null 时编译器会警告您)

There is C# 中可空 类 的特定约束,因此从编译时约束的角度来看 SomeRefType? 不匹配 T:class,但会匹配 T:class?.

where T : class The type argument must be a reference type. This constraint applies also to any class, interface, delegate, or array type. In a nullable context in C# 8.0 or later, T must be a non-nullable reference type.

where T : class? The type argument must be a reference type, either nullable or non-nullable. This constraint applies also to any class, interface, delegate, or array type.

所以可能在可为 null 的上下文中你会想要使用第二个:

public class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class?

不会对 string?string 发出任何警告。