Pergunta

I'm not quite sure how to phrase this question but the scenario is as follows:

Say I have the following class:

public class SampleClass
{
    public int Number { get; set; }
}

I know you can null coalesce the containing class:

SampleClass newSampleClass = possibleNullSampleClass ?? notNullSampleClass;

Is there any way to perform a sort of null coalesce on the property so I don't have to do this:

int? num = sampleClass != null ? new int?(sampleClass.Number) : 5;

It seems like it would be very useful to have something like a ??? operator to perform this check so I could do:

int? num = sampleClass.Number ??? 5;

Is anything like that possible in C#?

Foi útil?

Solução

Currently there is no such an operator. But in C# 6 "safe-navigation" operator will appear and you'll be able to write

int number = sampleClass?.Number;

This code won't fail with NullRef even if sampleClass equals null. For now you can use the following extension method that extracts value from an object and encapsulates null-check:

public static TResult Maybe<TSource, TResult>(
    this TSource source, Func<TSource, TResult> produceResult, Func<TResult> produceDefault)
    where TSource : class
{
    return source == null ? produceDefault() : produceResult(source);
}

and use it as follows:

int numberOrFive = sampleClass.Maybe(c => c.Number, () => 5);

Outras dicas

There is no existing operator to do that. You have shown one perfectly acceptable way of handling the problem.

If you wanted, you could wrap the logic in a method, but I'm not sure if that'd actually be worth the effort or not:

public static TResult Access<TSource, TResult>(
    TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
    where TSource : class
{
    if (obj == null)
        return defaultIfNull;
    else
        return selector(obj);
}

SampleClass sampleClass = null;
int num = Access(sampleClass, s => s.Number, 5);

(If you wanted, you could consider making that an extension method as well, although I personally am wary of extension methods on all classes. Also consider other names, such as Use.)

I'm going to propose a modification of Servy's post. I think his method would prove useful if it could handle the general case, where there can be a null anywhere up the object chain.

public static TResult Access<TSource, TResult>(
   TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
   where TSource : class
{
    TResult result;
    try
    {
        result = selector(obj);
    }
    catch ( NullReferenceException)
    {
        result = defaultIfNull;
    }

    return result;

}

This way if you are trying to access ZipCode = Customer.Address.ZipCode;

You are protected if either Customer or Address is null

You can't do that in C#. You need to explicitly test for nullity:

MyWidget x ;

int? v = x == null ?  (int?)x.SomeProperty : (int?) null ;

If you really think it would be useful, you could log your suggestion at Microsoft Connect:

http://connect.microsoft.com/VisualStudio

I'm willing to be that they thought about it and decided it wasn't sufficiently useful to build into the language.

You can totally do this:

var x = (myObject ?? DefaultObject).Field;

And this...

var x = (myObject == null) ? myObject.Field : defaultValue;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top