具有C#8可为空的引用类型的TryGetValue模式

时间:2019-04-04 22:58:40

标签: c# nullable

我正在将一些代码移植到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
    ...
}

还有其他选择吗?

2 个答案:

答案 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