我正在将一些代码移植到C#中以启用可为空的引用类型,并且我在代码中遇到了一些使用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
}
我们要在此处表达的模式是“如果返回值为true,则session
为非空。如果为false,则甚至不尝试查看会话,这是垃圾
问题是我现在收到session = null
的警告,但由于out
参数必须由函数填充,因此我不得不在其中放置某些东西。
这里有个不错的答案吗?我的想法:
我可以放弃TryGet
模式并包含可为空的引用类型(这是Swift这样的其他语言似乎所做的事情),例如
Session? GetSession(string key);
或者,我可以使用占位符值来实现我的“非空”承诺
public bool TryGetSession(string key, out Session session) {
session = new InvalidSession(); // assign default
...
}
还有其他选择吗?
答案 0 :(得分:4)
如果像我这样迟到,那么事实证明.NET团队通过MaybeNullWhen(returnValue: true)
空间中的一堆参数属性(例如System.Diagnostics.CodeAnalysis
)解决了该问题,您可以使用尝试模式。
返回快速样式的可为空的引用类型效果很好,但是使用try模式可以将诸如错误之类的内容作为附加的out参数返回。
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"
更多详细信息:
答案 1 :(得分:1)
我最终选择了迅捷的Session? GetSession()
null-safety意味着尝试不使用null对其进行检查就直接进入并使用该会话会产生警告,因此,当它为null时,您不会意外使用该值。 TryGet
试图达到同样的目的,所以我对此感到满意。
示例
var session = GetSession();
if(session == null)
return;
// now go and use session. Flow analysis knows that it's not null
另一种方法,即行数较少但标点符号较多:
if(!(GetSession() is Session session))
return;
// now go and use session. Flow analysis knows that it's not null