C#: 检查方法参数是否为字符串或空字符串?

3

我想检查一个方法的所有参数是否可为空。

例如:

public async Task<IActionResult> HierarchyOfRanking(sometype? orderByType)
{
}

对于 int? 可以通过以下方式进行检查:

paras.All(p => Nullable.GetUnderlyingType(p.ParameterType) != null)

(https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/builtin-types/nullable-value-types#how-to-identify-a-nullable-value-type)

但是,对于 string? 类型,它不起作用。我追踪发现,string? 的 ParameterType 不是 "string?" 而是 "string"。似乎对于所有引用类型(例如 string、user 等所有类), ? 只起到了一种注释的作用而不是语法符号。

例如,如果 a 是 int 类型, b 是 int? 类型,则 a = b 会导致错误。 但是如果 a 是 string 类型,b 是 string? 类型,则 a = b 只会引发警告。并且 string? 不被视为可空类型。typeof(string?) 会导致异常。

(https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/types#8-3-1-1-可空值类型)

因此问题是:有办法检查以下方法的 orderByType 参数是否可空吗?谢谢。

public async Task<IActionResult> HierarchyOfRanking(string? orderByType)
{
}

2
可空引用类型是编译时的一个特性。它与可空值类型不同。 - Crowcoder
那么这样做的方法就没有了吗? - cheny
2
不,因为字符串只是一个字符串。当你写String?时,它只是向编译器指示强制执行一些规则的标志。 - Crowcoder
无法将其作为可空引用类型进行,因为它仅在编译时存在。在编译的降级阶段,?会被删除。基本上,运行时看不到string?string之间的区别。此功能仅用于编译时静态分析。 - theemee
1
@theemee 虽然它是编译时特性,但这些信息在编译后仍必须存在于某个地方,不能被删除。否则,如果你引用已编译的第三方库(比如NuGet包),你的编译器怎么知道其中哪些成员是可为空的呢? - Evk
显示剩余2条评论
1个回答

4
你可以使用NullabilityInfoContext类来实现这个功能:
using System.Reflection;
public class Program
{
    public static void Main()
    {
        var method = typeof(Program).GetMethod("Test", BindingFlags.Static | BindingFlags.Public);
        var nullableParam = method.GetParameters()[0];        
        var notNullableParam = method.GetParameters()[1];
        var ctx = new NullabilityInfoContext();
        // for method parameter it doesn't matter whether you 
        // use WriteState or ReadState
        bool firstIsNullable = ctx.Create(nullableParam).WriteState == NullabilityState.Nullable;
        bool secondIsNullable = ctx.Create(notNullableParam).WriteState == NullabilityState.Nullable;
        Console.WriteLine("First is: " + (firstIsNullable ? "nullable" : "not nullable"));
        Console.WriteLine("Second is is: " + (secondIsNullable ? "nullable" : "not nullable"));
    }

    public static void Test(string? imNullable, string imNot) {
        Console.WriteLine(imNullable);
    }
}

输出 "第一个是:可空","第二个是:非可空"。请注意,如果您以这种方式检查第三方库,则私有和内部成员可能没有此元数据(取决于库的编译方式)。

有关此元数据在编译的二进制文件中存储方式的更多信息:此处


我刚回来,需要在投票之前检查一下 :) 谢谢 - cheny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接