简体   繁体   中英

Monadic null checking in C# 6.0

I stumbled across an interesting site, where some of the new (proposed) features of C# 6.0 are addressed. You may read it here: Probable C# 6.0 features .

What I find particular interesting is the monadic null checking (also known as the null-propagation operator ?. ). According to the site, the following statement

var bestValue = points?.FirstOrDefault()?.X ?? -1;

contains the monadic null check, which is currently implemented with this piece of code:

if (points != null) 
{
  var next = points.FirstOrDefault();
  if (next != null && next.X != null) return next.X;
}   
return -1;

My first glance was, hey, what the heck is written here? But after looking at the 'old' code, I am starting to like it.

However, I am also starting to get some questions, which I'd like to ask.

  • I assume that this null-propagating operator is thread safe. But how is that actually performed? Will race conditions be removed or are they persisting?
  • How would this operator handle generic types? Moreover, how would it deal with unconstrained generic types? For example, consider

     var resultAfterNullCheck = x?.Y; 

    If the type Y here is instantiated with reference types, non-nullable value types and nullable value types, there would be nothing reasonable to do (as I cannot think of what to do, as I simply do not know what to do). So is there a default that will be returned? Or will it throw an error?

  • When looking at the example the site provides (and which I copied above) I assume that one of the main benefits of the null-propagation operator will be that it will evaluate the statement only once. However (perhaps due to my lack of knowledge of CLR), I am quite curious on how it could be performed.
    As to me, the first evaluation (if points equals null) should trigger the extension method FirstOrDefault() to trigger when points isn't null, followed by the evalation of the returned type to be null or not, if not, X will be returned. So these are in fact three evaluations combined to one? Or am I understanding it incorrectly? Will this affect speed of execution?

In other words, what will be faster, the old way of performing null checks, or this new lovely operator? I will try to examine this by performing some research as soon as the download of Visual Studio 2015 is finished... But that requires a bit of patience...

Are there any thoughts on this new operator type? Is it really still a proposed one, or can we really expect to work with this new monadic null check?

EDIT
As Matthew Watson provided a nice MSDN article discussing this (and more) topic(s), I was curious if it mentioned my earlier question regarding unconstrained generics and how this operator deals with that. Unfortunately, I haven't found an answer yet. While I will suppose that the programmer should try to prevent the usage of unconstraint generics, I can still imagine that this is sometimes not feasible. If that is the case, will a redesign be really necessary?

You are way overthinking this. One by one, your questions:

  1. Why would you assume it's thread safe? Calling a member function isn't. This is nothing but calling a member function with a pre-check for nulls, so you only get as much thread safety as the original function guarantees.

  2. If your generic type allows null comparison (which is what this operator will use behind the scenes), then code will be emitted. If not you'll get a compile error (for example if you require the type to be a value type). That covers all cases!

  3. It is called once -- per operator, just like the normal . operator. If you say Abc it's still going to be two levels of indirection, and using this new operator is nothing different, it just checks for nulls too.

The real benefits of ?. are that it's semantic (you can tell at a glance what your code is trying to do) and short circuiting (makes code a lot shorter than nested if s). You aren't going to replace every . in your old code with ?. , in fact you'll probably rarely use it. But there are cases where it's going to be useful, like in Linq expressions following ...OrDefault() operations, or calling events.

To partially answer your first question, according to John Skeet on his blog , the null conditional operator ?. (= null propagation operator) is thread safe.

You can find everything about planned features in Roslyn project discussion. You can also try new features with console application using Roslyn like nuget-package (that means it works with Visual Studio 2013 <)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM