best way to prevent Null failure with string casting

24,968

Solution 1

Use the null-coalescing operator: ??

callReportCode = (reader["Call Report Code"] ?? "").ToString();

If the data in your field is DBNull.Value (rather than null), this will still work, because DBNull.Value is not null, so the ?? won't be used, and DBNull.Value.ToString() is "", which is what you'd want.

Solution 2

Convert.ToString(reader["Call Report Code"]);

It will return string.Empty if the value is null.

Source: http://msdn.microsoft.com/en-us/library/astxcyeh.aspx

Update: it also works with DBNull, I've just verified.

Update 2: I decided to bring a more complete test here, just to be sure:

DBNull dbNull = null;
DBNull dbNullEmpty = DBNull.Value;
string stringNull = null;
string stringEmpty = string.Empty;

var outcome1 = Convert.ToString(dbNull);//Empty string
var outcome2 = Convert.ToString(dbNullEmpty);//Empty string
var outcome3 = Convert.ToString(stringNull);//NULL
var outcome4 = Convert.ToString(stringEmpty);//Empty string

Solution 3

My suggestion is to never convert ToString when the data isn't a string, and if the data is already a string, then calling ToString is redundant, and a cast is all that's required.

I am making an assumption that the datatype in the database is integer, in which case, you can use a nullable int.

int? accountNumber = reader["Account Number"] == DBNull.Value ? null : (int?)reader["Account Number"];

I have made an extension method to do just this thing.

public static class SqlDataReaderExtensions
{
    public static T Field<T>(this SqlDataReader reader, string columnName)
    {
        object obj = reader[columnName];

        if (obj == null)
        {
            throw new IndexOutOfRangeException(
                string.Format(
                    "reader does not contain column: {0}",
                    columnName
                )
            );
        }

        if (obj is DBNull)
        {
            obj = null;
        }

        return (T)obj;
    }
}

Usage

int? accountType = reader.Field<int?>("Account Number"); // will return NULL or the account number.

Solution 4

If your string is nullable, you need to check the value returned from the SqlDataReader against DBNull.Value:

_callReportCode = reader["Call Report Code"] as string;

If the object returned by reader["Call Report Code"] is not a string, it's DBNull.Value, so the as cast is going to set the value of _callReportCode to null as well.

If you must set the string to a non-null in case the database value is missing, add ??, like this:

_callReportCode = (reader["Call Report Code"] as string) ?? string.Empty;

Solution 5

i have some easiest and common Method.

 public static string ToNULLString(this string Values)
        {
            if (string.IsNullOrEmpty(Values))
            {
                return "";
            }
            else
            {
                return Values.ToString();
            }
        }

use in C#

string item = null;
string value = item.ToNULLString();
Share:
24,968
jth41
Author by

jth41

Updated on February 07, 2020

Comments

  • jth41
    jth41 about 4 years
    _callReportCode = reader["Call Report Code"].ToString();
    

    I am attempting to handle the possibility for the object I am calling ToString on to be NULL. I am going to be using the above statement with several variables and I dont want to make an individual try/catch for each one... what is the best way to do null checking for strings.

    Other datatypes ive been doing this:

    int.TryParse(reader["Account Number"].ToString(), out _accountNumber);
    

    In this code "reader" refers to a SqlDataReader but thats not really important for this question.

  • Admin
    Admin about 11 years
    It will throw NPE if the object is null
  • Bobson
    Bobson about 11 years
    @0A0D - It'll only throw an exception if reader is null. This will work correctly if reader["Call Report Code"] is null.
  • Matthew
    Matthew about 11 years
    If the data is DBNull, you cannot use the null coalescing operator.
  • jth41
    jth41 about 11 years
    What do you do with the value later? like if I am going to pass it into a constructor? do I have to change that constructor to take a nullable int?
  • Bobson
    Bobson about 11 years
    @Matthew - Sure you can. DBNull.Value.ToString() returns "".
  • Matthew
    Matthew about 11 years
    That depends on your application, what does it mean to your application when Account Number is null?
  • Andre Calil
    Andre Calil about 11 years
    (DBNull.Value ?? "").ToString() doesn't even compile
  • Matthew
    Matthew about 11 years
    if the reader returns null for that column name, it means the column itself doesn't exist, if it returns DBNull, it means the database returned a null value. They are two distinct things, one is an application problem (you're requesting a column that doesn't exist), and the other isn't (column values can be null [DBNull]).
  • Bobson
    Bobson about 11 years
    @AndreCalil - That doesn't compile, but reader["Call Report Code"] is of type object, so the actual scenario will.
  • Andre Calil
    Andre Calil about 11 years
    @Bobson Yes, but DBNull inherits from Object (msdn.microsoft.com/en-us/library/system.dbnull.aspx). I can see that you've never used it in a real project. It will return DBNull from the DB if the column is null, it's a very usual problem.
  • Matthew
    Matthew about 11 years
    You cannot convert object to string using the null coalescing, you could cast it to string, however if the underlying data is neither null (not DBNull) nor string, you will get a cast exception. If you try and cast DBNull to string, you will get a cast exception.
  • Bobson
    Bobson about 11 years
    @Matthew - object foo = DateTime.Now; (foo ?? "").ToString(); works. object foo = 2.3; (foo ?? "").ToString(); works. object foo = null; (foo ?? "").ToString(); works. object foo = DBnull.Value; (foo ?? "").ToString(); works. Give me an example where you get an exception with this pattern.
  • jth41
    jth41 about 11 years
    It still throws an exception when I try this... _callReportCode = Convert.ToString(reader["Call Report Code"]); the whole point is to get it in that variable
  • Andre Calil
    Andre Calil about 11 years
    @John Can you share details of the exception?
  • Matthew
    Matthew about 11 years
    Sorry, I was using an erroneous example of string x = y ?? "";, I was missing the ToString portion.
  • Bobson
    Bobson about 11 years
    @Matthew - It's ok, I've been there. I'm sorry I got so defensive about it. I use this pattern a lot, so I was pretty confident in it.
  • Matthew
    Matthew about 11 years
    No need to apologize, I was the one who made this mistake.
  • Mohit Jain
    Mohit Jain almost 10 years
    Please explain your answer in very brief.
  • Anil
    Anil over 7 years
    it does not seems to be working the way msdn says, can be checked by Convert.ToString(null).EndsWith(""); vs string.empty.EndsWith(""); The stmt Convert.ToString(null).EndsWith("") will throw object ref exception.
  • Andre Calil
    Andre Calil over 7 years
    @AnilKumar yeah, but that's kinda expected. Convert.ToString(null) returns null, then you try to call the method .EndsWith("") from it.
  • Anil
    Anil over 7 years
    It will not return string.Empty if the value is null, it will return null.
  • Andre Calil
    Andre Calil over 7 years
    @AnilKumar I've updated the answer to bring all the situations, please check it out. Thanks!