具有 C# 8 可空引用类型的 TryGetValue 模式
TryGetValue pattern with C# 8 nullable reference types
我正在尝试将一些代码移植到 C# 以启用可为 null 的引用类型,并且我在我们的代码中遇到了一些使用 TryGetValue
模式的函数。
也就是像这样:
public bool TryGetSession(string key, out Session session) {
session = null; // assign default
// code which looks for a session based on the key, etc
// return true or false if we found the session key
}
我们在这里试图表达的模式是“如果 return 值为真,则 session
为 non-null。如果为假,则不要尝试看看 session,这是垃圾。
问题是我现在在 session = null
上收到警告,但我不得不将 东西 放在那里,因为 out
参数必须由函数。
这里有好的答案吗?我的想法:
我可以放弃 TryGet
模式并接受可为空的引用类型(这是 Swift 等其他语言似乎在做的事情)例如
Session? GetSession(string key);
或者,我可以使用占位符值来实现我的 "non-null" 承诺,例如
public bool TryGetSession(string key, out Session session) {
session = new InvalidSession(); // assign default
...
}
还有其他选择吗?
我最初选择了 swift 风格 Session? GetSession()
所以这个答案的原始版本是这么说的。
我后来根据 Nick Darvey 的回答改用 [NotNullWhen(returnValue: true)]
。由于 C# 具有 out var
特性(并且因为 C# 缺少 'if let'),TryGet
模式最终变得更加简洁且更适合。
注意:这些属性仅存在于 .NET Core 3.0 或更高版本中,它们不在桌面 .NET 框架中,但是您可以自己定义它们并将它们应用到您自己的方法中,它们会按预期工作。
如果你像我一样来晚了一点,事实证明 .NET 团队通过一堆参数属性解决了这个问题,比如 System.Diagnostics.CodeAnalysis
[=28] 中的 MaybeNullWhen(returnValue: true)
=] 可用于 try 模式。
返回一个 swift 风格的可空引用类型效果很好,但是 try 模式可以让你 return 像错误这样的东西作为额外的输出参数。
public bool TryGetSession(string key, [NotNullWhen(returnValue: true)] out Session? session, [NotNullWhen(returnValue: false)] out string? error)
{
// etc
}
// This is okay:
if(TryGetSession("cheese", out var session, out var error))
{
var time = session.Time;
}
// But this is not:
_ = TryGetSession("cheese", out var session, out var error);
var time = session.Time;
// "CS8602: Dereference of a potentially null reference"
更多详情:
我正在尝试将一些代码移植到 C# 以启用可为 null 的引用类型,并且我在我们的代码中遇到了一些使用 TryGetValue
模式的函数。
也就是像这样:
public bool TryGetSession(string key, out Session session) {
session = null; // assign default
// code which looks for a session based on the key, etc
// return true or false if we found the session key
}
我们在这里试图表达的模式是“如果 return 值为真,则 session
为 non-null。如果为假,则不要尝试看看 session,这是垃圾。
问题是我现在在 session = null
上收到警告,但我不得不将 东西 放在那里,因为 out
参数必须由函数。
这里有好的答案吗?我的想法:
我可以放弃 TryGet
模式并接受可为空的引用类型(这是 Swift 等其他语言似乎在做的事情)例如
Session? GetSession(string key);
或者,我可以使用占位符值来实现我的 "non-null" 承诺,例如
public bool TryGetSession(string key, out Session session) {
session = new InvalidSession(); // assign default
...
}
还有其他选择吗?
我最初选择了 swift 风格 Session? GetSession()
所以这个答案的原始版本是这么说的。
我后来根据 Nick Darvey 的回答改用 [NotNullWhen(returnValue: true)]
。由于 C# 具有 out var
特性(并且因为 C# 缺少 'if let'),TryGet
模式最终变得更加简洁且更适合。
注意:这些属性仅存在于 .NET Core 3.0 或更高版本中,它们不在桌面 .NET 框架中,但是您可以自己定义它们并将它们应用到您自己的方法中,它们会按预期工作。
如果你像我一样来晚了一点,事实证明 .NET 团队通过一堆参数属性解决了这个问题,比如 System.Diagnostics.CodeAnalysis
[=28] 中的 MaybeNullWhen(returnValue: true)
=] 可用于 try 模式。
返回一个 swift 风格的可空引用类型效果很好,但是 try 模式可以让你 return 像错误这样的东西作为额外的输出参数。
public bool TryGetSession(string key, [NotNullWhen(returnValue: true)] out Session? session, [NotNullWhen(returnValue: false)] out string? error)
{
// etc
}
// This is okay:
if(TryGetSession("cheese", out var session, out var error))
{
var time = session.Time;
}
// But this is not:
_ = TryGetSession("cheese", out var session, out var error);
var time = session.Time;
// "CS8602: Dereference of a potentially null reference"
更多详情: