在C#类中有一个模式,以Dictionary.TryGetValue
和表示int.TryParse
:一种方法,该方法返回指示操作成功的布尔值和包含实际结果的out参数;如果操作失败,则将out参数设置为null。
假设我正在使用C#8不可为空的引用,并且想为自己的类编写一个TryParse方法。在正确的签名是这样的:
public static bool TryParse(string s, out MyClass? result);
因为在错误情况下结果为null,所以必须将out变量标记为可为空。
但是,通常使用Try模式,如下所示:
if (MyClass.TryParse(s, out var result))
{
// use result here
}
因为我仅在操作成功时才进入分支,所以结果在该分支中永远不能为null。但是因为我将其标记为可为空,所以现在我必须检查它或使用它!
来覆盖:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // compiler warning, could be null
Console.WriteLine("Look: {0}", result!.SomeProperty); // need override
}
这很丑陋,有点不符合人体工程学。
由于典型的使用模式,我还有另一种选择:关于结果类型:
public static bool TryParse(string s, out MyClass result) // not nullable
{
// Happy path sets result to non-null and returns true.
// Error path does this:
result = null!; // override compiler complaint
return false;
}
现在,典型用法变得更好:
if (MyClass.TryParse(s, out var result))
{
Console.WriteLine("Look: {0}", result.SomeProperty); // no warning
}
但非典型用法不会得到警告,它应该:
else
{
Console.WriteLine("Fail: {0}", result.SomeProperty);
// Yes, result is in scope here. No, it will never be non-null.
// Yes, it will throw. No, the compiler won't warn about it.
}
现在,我不确定该走哪条路。C#语言团队有官方建议吗?是否有已经转换为非空引用的CoreFX代码可以向我展示如何执行此操作?(我一直在寻找TryParse
方法。IPAddress
是具有一个类的类,但是尚未在corefx的master分支上进行转换。)
像这样的通用代码如何Dictionary.TryGetValue
处理呢?(可能具有MaybeNull
我发现的特殊属性。)当我实例化Dictionary
具有非空值类型的a 时会发生什么?
MyClass?
),并使用case MyClass myObj:
和(可选)在其上进行切换case null:
。