在C#中测试空值

时间:2011-06-08 15:01:48

标签: c# dataset

如果我这样做:

DataSet ds = GetMyDataset();

try
{
    string somevalue = ds.Tables[0].Rows[0]["col1"];
}
catch
{
    //maybe something was null
}

有没有一种不使用try / catch检查空值的好方法?只是我不关心“col1”中的值是否为空,或者如果“col1”不存在,或者如果没有返回行,或者如果表不存在,则不在乎!

也许我应该关心? :) 也许try / catch是接近这个的最佳方式,但我只是想知道是否还有其他方法可以做到这一点?

谢谢!

14 个答案:

答案 0 :(得分:7)

不关心桌子或柱子有点奇怪。

例如,期待table[0].Rows.Count == 0是一种更为常见的做法。

检查NULL值的最佳方法是使用if(...) ... else ... 最糟糕的方式是等待例外(以任何方式)。

答案 1 :(得分:4)

if (ds == null
    || ds.Tables == null 
    || ds.Tables.Count == 0
    || ds.Tables[0].Rows == null 
    || ds.Tables[0].Rows.Count == 0
    || ds.Tables[0].Rows[0].IsNull("col1")
)
//there is no data...
...

答案 2 :(得分:3)

如果您想确保您的代码不会失败,您实际上必须检查层次结构中的所有元素,例如:

string someValue = "";

if (ds != null &&
    ds.Tables != null &&
    ds.Tables.Any() &&
    ds.Tables[0].Rows != null &&
    ds.Tables[0].Rows.Any() &&
    ds.Tables[0].Rows[0]["col1"] != DBNull.Value)
{
    someValue = ds.Tables[0].Rows[0]["col1"];
}

答案 3 :(得分:2)

DataSet ds = GetMyDataset();

string somevalue = ds != null ? ds.Tables[0].Rows[0]["col1"].ToString() : null;

答案 4 :(得分:1)

你或许可以使用可空的三元组'??',但我认为返回的null是'DBNull'而不是'null'。

例子是......

string somevalue = ds.Tables[0].Rows[0]["col1"] ?? "";

答案 5 :(得分:1)

做一些检查:

string somevalue = String.Empty;
if (ds.Tables.Count > 0)
        {
            System.Data.DataTable dt = ds.Tables[0];
            if (dt.Rows.Count > 0)
            {
                System.Data.DataRow dr = dt.Rows[0];
                if (dt.Columns.Count>0 && dt.Columns.Contains("col1"))
                {
                   somevalue = dr["col1"].ToString();
                }
            }
        }

答案 6 :(得分:0)

你必须从顶部开始(这是DataSet)逐个检查所有null(或其他null类型)

if(ds!= null) if(table!= null) ...

你可以不用,但你的代码更容易出错。

答案 7 :(得分:0)

从维护的角度来看,你正在做的事情是非常可取的。

否则,您必须:检查DS是否为null,检查DataSet中是否有任何表,检查表中是否有任何行,检查列是否存在,检查以查看如果列中有任何数据。

它肯定会消除很多繁琐的代码。

答案 8 :(得分:0)

我过去使用的是Null测试的一个小包装器,它返回一个默认值。例如:

    /// <summary>
    /// Test DBValue for DBNull and return NullReplaceValue if DBValue is DBNull
    /// </summary>
    /// <returns>Returns NullReplaceValue if DBValue is DBNull</returns>
    public static string NullStr(object DBValue, string NullReplaceValue)
    {
        if (object.ReferenceEquals(DBValue, DBNull.Value)) {
            return NullReplaceValue;
        } else {
            return Convert.ToString(DBValue);
        }
    }

使用中:

string somevalue = MyNullTests.NullStr(ds.Tables[0].Rows[0]["col1"], "Value was null");

答案 9 :(得分:0)

我认为你应该明确表示你并不关心所有这些事情,这意味着你应该明确地处理每一个案例:

if (ds.Tables.Count == 0)
  return null;

var table = ds.Tables[0];
if (table.Rows.Count == 0)
  return null;

if (!table.Columns.Contains("col1"))
  return null;

var row = ds.Rows[0];
if (row.IsNull("col1"))
  return null;

return row["col1"]

这是更多的代码,但对我而言,它更清楚地传达了意图。

答案 10 :(得分:0)

我认为May be Monad对于这种情况是最好的(Sample来自源代码):

public static TResult With<TInput, TResult>(this TInput o, 
       Func<TInput, TResult> evaluator)
       where TResult : class where TInput : class
{
  if (o == null) return null;
  return evaluator(o);
}

string postCode = this.With(x => person)
                      .With(x => x.Address)
                      .With(x => x.PostCode)

对于您的情况类似于:

ds.With(x=>Tables[0]).With(x=>x.Rows).With(x=>x[0])...

您将创建一个扩展类并使用它而不必担心空引用,另外Return方法对于您看到链接很有用。

答案 11 :(得分:0)

如果你真的要发送随机的,未经验证的数据集,索引和名称,你可以像这样做一个辅助方法:

public static Object GetDataSetValue(DataSet dataSet, int tableIndex, int rowIndex, string columnName)
{
    Object value = null;

    if (dataSet != null
        && tableIndex >= 0
        && tableIndex < dataSet.Tables.Count
        && rowIndex >= 0
        && rowIndex < dataSet.Tables[tableIndex].Rows.Count
        && dataSet.Tables[tableIndex].Columns.Contains(columnName))
    {
        value = dataSet.Tables[tableIndex].Rows[rowIndex][columnName];
    }

    return value;
}

然后使用类似GetDataSetValue(ds, 0, 0, "col1")的内容。

答案 12 :(得分:0)

我讨厌不得不处理不能保证标准结果集的数据访问层:任何给定的SQL查询或存储过程应该始终返回相同的结果集模式。处理空集(又名DataTables)很容易。处理任意缺失的对象引用......不是那么多。

正确的答案是修复您的数据访问代码,使其返回一致的架构。

如果不这样做,如果我必须处理像我这样做的代码:

DataSet   ds         = ExecuteStoredProcedure();
DataTable dt         = ( ds != null && ds.Tables != null ? ds.Tables[0] : null ) ;
DataRow   dr         = ( dt != null && dt.Rows   != null ? dt.Rows[0]   : null ) ;
object    o          = ( dr != null ? dr["someColumn"]) : null ) ;
string    someColumn = (string) colName ;

在调试器中或通过日志记录调试很容易。给出5个值的集合,您可以很容易地看到存在的内容和缺失的内容。它可以很容易地看出违反了什么假设(约束?)。

答案 13 :(得分:-1)

检查DBNull.Value,例如

if (ds.Tables[0].Rows[0]["col1"] != DBNull.Value)