我正在尝试使用 roslyn 分析类型声明是否是“可为空引用”类型(C#8)
我打算看看
TypeSyntex
是否是NullableTypeSyntax
以及ITypeSymbol.IsReferenceType
是否是true
。
以下代码在大多数情况下都有效,但当声明的类型是泛型时,即失败,即
List<T>?
void Main()
{
string text = @"
#nullable enable
public class MyClass
{
public string? Get() => null;
public List<string>? GetGeneric() => null;
}";
SyntaxTree tree = CSharpSyntaxTree.ParseText(text);
PortableExecutableReference mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
CSharpCompilation compilation = CSharpCompilation.Create("RefitCompilation", syntaxTrees: new[] { tree }, references: new[] { mscorlib });
SemanticModel semanticModel = compilation.GetSemanticModel(tree);
MethodDeclarationSyntax nonGenericMethodSyntax = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
ITypeSymbol nonGenericReturnType = semanticModel.GetTypeInfo(nonGenericMethodSyntax.ReturnType).Type;
bool isNullableTypeReference = nonGenericMethodSyntax.ReturnType is NullableTypeSyntax && nonGenericReturnType.IsReferenceType;
Console.WriteLine($@"NonGeneric Nullalbe Reference: `{nonGenericMethodSyntax}`
Is Nullable Type Reference: {isNullableTypeReference}
Original Definition: {nonGenericReturnType.OriginalDefinition},
IsNullableTypeSyntax: {nonGenericMethodSyntax.ReturnType is NullableTypeSyntax}
Is Reference Type: {nonGenericReturnType.IsReferenceType}");
Console.WriteLine();
MethodDeclarationSyntax genericMethodSyntax = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Last();
ITypeSymbol genericReturnType = semanticModel.GetTypeInfo(genericMethodSyntax.ReturnType).Type;
isNullableTypeReference = genericMethodSyntax.ReturnType is NullableTypeSyntax && genericReturnType.IsReferenceType;
Console.WriteLine($@"Generic Nullalbe Reference: `{genericMethodSyntax}`
Is Nullable Type Reference: {isNullableTypeReference}
Original Definition: {genericReturnType.OriginalDefinition},
IsNullableTypeSyntax: {genericMethodSyntax.ReturnType is NullableTypeSyntax}
Is Reference Type: {genericReturnType.IsReferenceType}");
}
输出
NonGeneric Nullalbe Reference: `public string? Get() => null;`
Is Nullable Type Reference: True
Original Definition: string,
IsNullableTypeSyntax: True
Is Reference Type: True
Generic Nullalbe Reference: `public List<string>? GetGeneric() => null;`
Is Nullable Type Reference: False
Original Definition: System.Nullable<T>,
IsNullableTypeSyntax: True
Is Reference Type: False
为什么
List<T>?
原来的定义是System.Nullable<T>
?如何确定类型是否为可空引用类型?
这不是一个完整的答案,但我有同样的问题,这是我对事物的解释。
在
string text = @"
#nullable enable
public class MyClass
{
public string? Get() => null;
public List<string>? GetGeneric() => null;
}";
List<string>?
无效,System.Collections.Generic
使用缺失,因此无法确定List<string>
的类型。
接下来发生的是未知的
List<T>?
类型被解释为可为 null 的结构,因此我们到达 Nullable<List<string>>
。
可以通过询问
Nullable
的基础类型并检查其 TypeKind
来检查这种情况,即
((INamedTypeSymbol)type).TypeArguments[0].TypeKind
将产生
Error
。