What is the proper way to check for null values?

2019-01-12 18:21发布

I love the null-coalescing operator because it makes it easy to assign a default value for nullable types.

 int y = x ?? -1;

That's great, except if I need to do something simple with x. For instance, if I want to check Session, then I usually end up having to write something more verbose.

I wish I could do this:

string y = Session["key"].ToString() ?? "none";

But you can't because the .ToString() gets called before the null check so it fails if Session["key"] is null. I end up doing this:

string y = Session["key"] == null ? "none" : Session["key"].ToString();

It works and is better, in my opinion, than the three-line alternative:

string y = "none";
if (Session["key"] != null)
    y = Session["key"].ToString();

Even though that works I am still curious if there is a better way. It seems no matter what I always have to reference Session["key"] twice; once for the check, and again for the assignment. Any ideas?

10条回答
趁早两清
2楼-- · 2019-01-12 18:47

You could also use as, which yields null if the conversion fails:

Session["key"] as string ?? "none"

This would return "none" even if someone stuffed an int in Session["key"].

查看更多
smile是对你的礼貌
3楼-- · 2019-01-12 18:49

If you're frequently doing this specifically with ToString() then you could write an extension method:

public static string NullPreservingToString(this object input)
{
    return input == null ? null : input.ToString();
}

...

string y = Session["key"].NullPreservingToString() ?? "none";

Or a method taking a default, of course:

public static string ToStringOrDefault(this object input, string defaultValue)
{
    return input == null ? defaultValue : input.ToString();
}

...

string y = Session["key"].ToStringOrDefault("none");
查看更多
一夜七次
4楼-- · 2019-01-12 18:52

If it will always be a string, you can cast:

string y = (string)Session["key"] ?? "none";

This has the advantage of complaining instead of hiding the mistake if someone stuffs an int or something in Session["key"]. ;)

查看更多
我想做一个坏孩纸
5楼-- · 2019-01-12 18:53

All of the suggested solutions are good, and answer the question; so this is just to extend on it slightly. Currently the majority of answers only deal with null validation and string types. You could extend the StateBag object to include a generic GetValueOrDefault method, similar to the answer posted by Jon Skeet.

A simple generic extension method that accepts a string as a key, and then type checks the session object. If the object is null or not the same type, the default is returned, otherwise the session value is returned strongly typed.

Something like this

/// <summary>
/// Gets a value from the current session, if the type is correct and present
/// </summary>
/// <param name="key">The session key</param>
/// <param name="defaultValue">The default value</param>
/// <returns>Returns a strongly typed session object, or default value</returns>
public static T GetValueOrDefault<T>(this HttpSessionState source, string key, T defaultValue)
{
    // check if the session object exists, and is of the correct type
    object value = source[key]
    if (value == null || !(value is T))
    {
        return defaultValue;
    }

    // return the session object
    return (T)value;
}
查看更多
神经病院院长
6楼-- · 2019-01-12 18:55

create an auxiliary function

public static String GetValue( string key, string default )
{
    if ( Session[ key ] == null ) { return default; }
    return Session[ key ].toString();
}


string y = GetValue( 'key', 'none' );
查看更多
手持菜刀,她持情操
7楼-- · 2019-01-12 18:58

Skeet's answer is the best - in particularly I think his ToStringOrNull() is quite elegant and suits your need best. I wanted to add one more option to the list of extension methods:

Return original object or default string value for null:

// Method:
public static object OrNullAsString(this object input, string defaultValue)
{
    if (defaultValue == null)
        throw new ArgumentNullException("defaultValue");
    return input == null ? defaultValue : input;
}

// Example:
var y = Session["key"].OrNullAsString("defaultValue");

Use var for the returned value as it will come back as the original input's type, only as the default string when null

查看更多
登录 后发表回答