TryGetValue pattern with C# 8 nullable reference types

早过忘川 提交于 2020-04-06 04:38:15

问题


I'm playing with porting some code to C# to enable nullable reference types, and I've encountered some functions in our code that use the TryGetValue pattern.

That is, something like this:

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
}

The pattern which we're trying to express here is "if the return value is true, then session is non-null. If false, then don't even attempt to look at the session, it's garbage.

The problem is I now get a warning on session = null, but I'm forced to put something there as out parameters MUST be populated by the function.

Is there a good answer here? My thoughts:

I could drop the TryGet pattern and embrace the nullable reference types (This is what other languages like Swift seem to do) e.g.

Session? GetSession(string key);

Or, I could live up to my "non-null" promise using a placeholder value e.g.

public bool TryGetSession(string key, out Session session) {
    session = new InvalidSession(); // assign default
    ...
}

Are there any other options?


回答1:


If you're arriving at this a little late, like me, it turns out the .NET team addressed it through a bunch of parameter attributes like MaybeNullWhen(returnValue: true) in the System.Diagnostics.CodeAnalysis space which you can use for the try pattern.

Returning a swift-style nullable reference type works well, but the try pattern lets you return things like errors as additional out parameters.

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"

Further details:

  • Documentation about the attributes
  • Language Design Meeting about it.



回答2:


I originally ended up going with the swift-style Session? GetSession() so the original version of this answer said that.

I later switched to using [NotNullWhen(returnValue: true)] as per Nick Darvey's answer. Because of the out var feature that C# has (and because C# lacks 'if let'), the TryGet pattern ends up being more concise and a better fit.

Note: These attributes only exist in .NET Core 3.0 or greater, they're not in the desktop .NET framework, however you can define them yourself and apply them to your own methods and they work as expected.



来源:https://stackoverflow.com/questions/55526064/trygetvalue-pattern-with-c-sharp-8-nullable-reference-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!