Подтвердить что ты не робот

Проверка нулевых значений в С#

Если я сделаю что-то вроде:

DataSet ds = GetMyDataset();

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

Есть ли хороший способ проверить нулевые значения без использования try/catch? Это просто, что мне все равно, если значение в "col1" равно null, или если "col1" не существует, или если не было возвращенных строк, OR, если таблица не существует!

Может, мне все равно?:) Может быть, try/catch - лучший способ приблизиться к этому, но я просто задавался вопросом, есть ли другой способ сделать это?

Спасибо!

4b9b3361

Ответ 1

Я думаю, Может быть, Монада лучше всего подходит для этой ситуации (Образец из источника):

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 полезен для ссылки на ссылку.

Ответ 2

Это странно, если не заботиться о Столе или Столбе.

Это гораздо более обычная практика, например, ожидать table[0].Rows.Count == 0.

И лучший способ проверить значения NULL - if(...) ... else ....
Хуже всего ждать Exceptions (каким бы то ни было способом).

Ответ 3

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...
...

Ответ 4

Если вы хотите убедиться, что ваш код не будет работать, вам действительно нужно будет проверить все элементы в иерархии, например:

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"];
}

Ответ 5

DataSet ds = GetMyDataset();

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

Ответ 6

вы могли бы использовать nullabel terinary '??', но я думаю, что возвращаемое значение null является "DBNull", а не "null".

Пример будет...

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

Ответ 7

Сделайте несколько проверок:

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();
                }
            }
        }

Ответ 8

Вам нужно будет проверить их все для нулевого (или других типов нулей) один за другим, начиная с вершины (который является DataSet)

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

вы можете сделать это без, но ваш код будет намного более восприимчивым к ошибкам.

Ответ 9

С точки зрения обслуживания, то, что вы делаете, очень желательно.

В противном случае вам необходимо: проверить, является ли DS нулевым, проверить, есть ли какие-либо таблицы в DataSet, проверить, есть ли какие-либо строки в таблице, проверить, существует ли столбец, проверить, есть ли если в столбце есть какие-либо данные.

Это, безусловно, устранит много утомительного кода.

Ответ 10

То, что я использовал в прошлом, представляет собой небольшую оболочку тестов 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");

Ответ 11

Я думаю, вы должны четко указать, что вы не заботитесь обо всех этих вещах, а это означает, что вы должны обрабатывать каждый случай явно:

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"]

Это больше кода, но для меня он более четко передает намерение.

Ответ 12

Если вы действительно отправляете случайные, не проверенные наборы данных, индексы и имена, вы можете использовать вспомогательный метод, подобный этому:

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").

Ответ 13

Мне не нравится иметь дело с уровнем доступа к данным, который не гарантирует мне стандартный набор результатов: любой SQL-запрос или хранимая процедура должны всегда возвращать одну и ту же схему набора результатов. Работа с пустыми наборами (aka 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 значений, вы можете легко увидеть, что присутствовало и чего не хватало. Это позволяет легко понять, какое предположение (ограничение?) Было нарушено.

Ответ 14

Вы проверяете DBNull.Value, например,

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