使用字符串转换时,避免 Null 失败的最佳方法是什么?

10
_callReportCode = reader["Call Report Code"].ToString();

我正在尝试处理可能为空的对象调用ToString方法的情况。由于我将在几个变量中使用上述语句,我不想为每个变量创建单独的try/catch块... 那么如何最好地检查字符串是否为空?

其他数据类型的处理方式:

int.TryParse(reader["Account Number"].ToString(), out _accountNumber);
在这段代码中,“reader”指的是SqlDataReader,但对于这个问题并不重要。

https://dev59.com/VWw15IYBdhLWcg3wv-ba#10104842 - user195488
如果您想进行单独测试,try/catch 不是适当的机制 - 在调用 .ToString() 之前,您应该检查 reader['blah'] 是否为 Null。异常永远不应成为您的正常执行流程的一部分,它们昂贵且不是以这种方式使用的(例如,如果您没有仔细思考,很容易捕获错误的东西)。 - Basic
1
无关的,但我很好奇账号应该是一个整数。 - Anthony Pegram
尽管我同意得票最多的答案,但我认为你应该编写一个扩展方法以便在任何地方重用你的代码。我不太喜欢反复使用相同的代码。 - Tarik
11个回答

32

使用空值合并运算符: ??

callReportCode = (reader["Call Report Code"] ?? "").ToString();
如果您字段中的数据为 DBNull.Value(而不是null),这仍然有效,因为 DBNull.Value 不是 null,所以 ?? 将不会被使用, 并且 DBNull.Value.ToString()"",这正是您想要的。

1
如果数据是 DBNull,则不能使用空值合并运算符。 - Matthew
1
@Matthew - 当然可以。DBNull.Value.ToString() 返回 "" - Bobson
2
(DBNull.Value ?? "").ToString() 甚至无法编译 - Andre Calil
1
@Bobson 是的,但 DBNull 继承自 Object(http://msdn.microsoft.com/en-us/library/system.dbnull.aspx)。我可以看出你从未在真实项目中使用过它。如果列为空,它将从数据库返回 DBNull,这是一个非常普遍的问题。 - Andre Calil
2
不用道歉,是我犯了这个错误。 - Matthew
显示剩余8条评论

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

如果值为null,则会返回string.Empty

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

更新:我刚刚验证了,它也适用于DBNull

更新2:我决定在这里带来一个更完整的测试,以确保:

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

当我尝试这样做时,它仍然会抛出异常... _callReportCode = Convert.ToString(reader["Call Report Code"]); 整个重点是将其放入该变量中。 - jth41
@John 你能分享一下异常的细节吗? - Andre Calil
它似乎不按照 MSDN 所说的方式工作,可以通过 Convert.ToString(null).EndsWith(""); vs string.empty.EndsWith(""); 进行检查。语句 Convert.ToString(null).EndsWith("") 将抛出对象引用异常。 - Anil
@AnilKumar 是的,但这是可以预料的。Convert.ToString(null)返回null,然后你试图从它调用方法.EndsWith("") - Andre Calil
如果值为null,它不会返回string.Empty,而是返回null。 - Anil
@AnilKumar,我已经更新了回答,涵盖了所有情况,请查看一下。谢谢! - Andre Calil

3

如果您的字符串是可空的,您需要检查从SqlDataReader返回的值是否等于DBNull.Value:

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

如果reader["Call Report Code"]返回的对象不是string,那么它就是DBNull.Value,因此as转换将同样把_callReportCode的值设置为null
如果数据缺失时必须将字符串设置为非空值,请添加??,如下所示:
_callReportCode = (reader["Call Report Code"] as string) ?? string.Empty;

3
我的建议是当数据不是字符串时,永远不要将其转换为ToString。如果数据已经是字符串,则调用ToString是多余的,只需要强制转换即可。
我假设数据库中的数据类型是整数,在这种情况下,您可以使用可空整数。
int? accountNumber = reader["Account Number"] == DBNull.Value ? null : (int?)reader["Account Number"];

我制作了一个扩展方法来完成这件事。
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;
    }
}

用法

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

你后面要如何处理这个值?比如说,如果我想将它传递给构造函数,我需要修改构造函数以接收可空的整数吗? - jth41
这取决于您的应用程序,当“账户号码”为空时,对您的应用程序意味着什么? - Matthew

1
我有一些最简单和常见的方法。
 public static string ToNULLString(this string Values)
        {
            if (string.IsNullOrEmpty(Values))
            {
                return "";
            }
            else
            {
                return Values.ToString();
            }
        }

使用C#。
string item = null;
string value = item.ToNULLString();

1
我所找到的最简单的方法是:
_callReportCode = reader["Call Report Code"] + "";

请简要解释你的答案。 - Mohit Jain

0
请使用以下代码行:
_callReportCode = String.IsNullorEmpty(reader["Call Report Code"]) ?
                  String.Empty :
                  reader["Call Report Code"].ToString();

请使用以下代码替换此行:

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

0

_callReportCode = Convert.ToString(reader["Call Report Code"]) 应确保其中没有空值。


0

你可以创建一个方法,在需要进行检查时调用该方法。 这样,你只需要输入一次 try catch... 或者你可以为字符串类创建一个扩展方法来实现这个功能


0

我喜欢使用空值合并运算符空值条件运算符的组合:

string nn = MyObject.myNullableVar?.ToString() ?? "";

这基本上与这个相同

string ss = (MyObject.MyNullableVar == null) ? "" : MyObject.MyNullableVar.ToString();

但更短。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接