2

改写的问题: 我有这个具有泛型类型的相等比较器限制为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);
}

当一个班级让我们说

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

由代码生成器使用

[Generator]
public class MyCodeGenerator : ISourceGenerator
{
}

NetAnalyzer 说string?有一个 TypeKind 类

但是当我这样做时,

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

它说不string?符合“类”约束。即使分析器告诉我它是一个类,我是否在这里遗漏了什么?还是我误解了这个概念?

原始问题:根据微软文档中对Nullable的描述,它们被归类为structs,但为什么 CodeAnalyzer 告诉我 TypeKind 的 TypeKindstring?是 TypeKind.Class?

这是一些上下文,在我正在编写的库中,针对源生成(C# 9 源生成器)分析类,这基本上是使用 .NetAnalyzer。将检查类的每个属性是否将它们的类型视为类。事实证明,它string?被视为一个类。

4

2 回答 2

4

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

where T : class类型参数必须是引用类型。此约束也适用于任何类、接口、委托或数组类型。在 C# 8.0 或更高版本的可为空上下文中,T 必须是不可为空的引用类型

where T : class?类型参数必须是引用类型,可以为空或不可为空。此约束也适用于任何类、接口、委托或数组类型。

因此,可能在可为空的上下文中,您将需要使用第二个:

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

这不会给出任何警告,无论是 forstring?还是 for string

于 2021-05-07T17:54:09.727 回答
1

stringsNullable是类,由于泛型约束,不能用作泛型类型参数where T : struct。在您的上下文中string?是一个可为空的引用类型,它可用于向编译器指示引用类型不应null作为值(变量仍然可以null作为值并应null在公共 API 中检查值,但编译器会警告您当您null在不可为空的上下文中使用时)

于 2021-05-07T17:22:46.290 回答