Null Conditional Operator, not behaving as expecte

2019-07-15 03:36发布

问题:

I have the following code in a DelegatingHandler for a WebApi 2 project.

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var content = await request.Content?.ReadAsStringAsync();
        _log.Information("Received {request} with content body: {content}.", request, content);

        // Run the rest of the request pipeline.
        var result = await base.SendAsync(request, cancellationToken);

        var responseContent = await result.Content?.ReadAsStringAsync();
        _log.Information("Returning {result} with content body: {responseContent}.", result, responseContent);

        return result;
    }

On my machine this works as expected and during a response that is a 301 Redirect (where result.content would be null) I get responseContent == null; however, on a co-workers machine he receives a null reference exception on this line. We are both using the 4.5.1 runtime, the differences as far as we can tell is as follows follows:

  • I'm using VS2015 Enterprise SP2 (where it works), he's using VS2015 Professional SP2 (where it doesn't work)

Ninja Edit - the .NET versions and service packs I have installed as well as the ones he has installed...

It looks like the machine where it is not working has two 4.5.1 security updates installed (KB2901126 & KB2931368) that I do not, would one of these cause this issue? Is there a difference in the compilers or compiler options that I need to check? Or am I looking into something that has a simpler explanation?

回答1:

I don't know what the difference between the two machines is, but your code is wrong:

await result.Content?.ReadAsStringAsync();

What this does, is that when result.Content is not null, ReadAsStringAsync() is called and its result is awaited, as it should. But when result.Content is null, the whole subexpression result.Content?.ReadAsStringAsync() is null, which means that the await will throw a NullReferenceException.

So, if you want to protect against result.Content being null, you should probably use an old-fashioned if or a ternary operator.