Общий метод может обработать и типы Значения Ссылки и Nullable?

Ну, я получил ответ, пытаясь просто вернуться

return Json("",JsonRequestBehavior.AllowGet);

, и мы готовы пойти на успешный ответ Ajax.

12
задан Adam Lassek 19 November 2008 в 20:40
поделиться

8 ответов

Можно просто объявить метод как это:

public static T GetNullable<T>(this IDataRecord dr, int ordinal)
{
    return dr.IsDBNull(ordinal) ? default(T) : (T) dr.GetValue(ordinal);
}

Таким образом, если T является nullable интервалом или каким-либо другим nullable типом значения, он на самом деле возвратит пустой указатель. Если это будет регулярный тип данных, то это просто возвратит значение по умолчанию для того типа.

10
ответ дан 2 December 2019 в 22:06
поделиться

Это работает:

public static T Get<T>( this IDataRecord dr, int ordinal) 
{
    T  nullValue = default(T);
    return dr.IsDBNull(ordinal) ? nullValue : (T) dr.GetValue(ordinal);
}


public void Code(params string[] args)
{
    IDataRecord dr= null;
    int? a = Get<int?>(dr, 1);
    string b = Get<string>(dr, 2);
}
2
ответ дан 2 December 2019 в 22:06
поделиться

Я не думаю, что можно реализовать это с единственной функцией. Если бы C# поддерживал перегрузку на основе типа возврата, Вы смогли, но даже затем я рекомендовал бы против выполнения так.

Необходимо смочь выполнить то же самое, не используя nullable типы данных и возвратить или фактическое значение или пустой указатель, как предложено BFree.

1
ответ дан 2 December 2019 в 22:06
поделиться

Вы не можете сделать этого с одним методом, но Вы делаете это с три:

public static T GetData<T>(this IDataReader reader, Func<int, T> getFunc, int index)
{
    if (!reader.IsClosed)
    {
        return getFunc(index);
    }
    throw new ArgumentException("Reader is closed.", "reader");
}

public static T GetDataNullableRef<T>(this IDataReader reader, Func<int, T> getFunc, int index) where T : class
{
    if (!reader.IsClosed)
    {
        return reader.IsDBNull(index) ? null : getFunc(index);
    }
    throw new ArgumentException("Reader is closed.", "reader");
}

public static T? GetDataNullableValue<T>(this IDataReader reader, Func<int, T> getFunc, int index) where T : struct
{
    if (!reader.IsClosed)
    {
        return reader.IsDBNull(index) ? (T?)null : getFunc(index);
    }
    throw new ArgumentException("Reader is closed.", "reader");
}

Затем для использования его Вы сделали бы:

private static Whatever CreateObject(IDataReader reader)
{
    Int32? id = reader.GetDataNullableValue<Int32>(reader.GetInt32, 0);
    string name = reader.GetDataNullableRef<string>(reader.GetString, 1);
    Int32 x = reader.GetData<Int32>(reader.GetInt32, 2);
}
0
ответ дан 2 December 2019 в 22:06
поделиться

Я делаю это этот путь:

DataRow record = GetSomeRecord();
int? someNumber = record[15] as int?
Guid? someUID = record["MyPrimaryKey"] as Guid?;
string someText = GetSomeText();
record["Description"] = someText.ToDbString();

// ........

public static class StringExtensionHelper {
    public static object ToDbString( this string text ) {
         object ret = null != text ? text : DBNull.Value
         return ret;
    }
}

Править: Вы можете (или Вы должны) иметь "ToDbInt32, ToDbBool, и т.д...." дополнительные методы для других типов примитивов, конечно.

РЕДАКТИРОВАНИЕ 2: можно также расширить базовый класс "объект" с помощью "ToDbValue".

public static class StringExtensionHelper {
    public static object ToDbValue( this object value ) {
         object ret = object.ReferenceEquals( value, null ) ? (object)DBNull.Value : value;
         return ret;
    }
}
-2
ответ дан 2 December 2019 в 22:06
поделиться

Структура Nullable только для типов Значения, потому что ссылочные типы nullable так или иначе...

-1
ответ дан 2 December 2019 в 22:06
поделиться
public static T Get<T>(this IDataRecord rec, Func<int, T> GetValue, int ordinal)
{
    return rec.IsDBNull(ordinal) ? default(T) : GetValue(ordinal);
}

или более высокая производительность

public static T Get<T>(this IDataRecord rec, Func<IDataRecord, int, T> GetValue, int ordinal)
{
    return rec.IsDBNull(ordinal) ? default(T) : GetValue(rec, ordinal);
}

public static Func<IDataRecord, int, int> GetInt32 = (rec, i) => rec.GetInt32(i);
public static Func<IDataRecord, int, bool> GetBool = (rec, i) => rec.GetBoolean(i);
public static Func<IDataRecord, int, string> GetString = (rec, i) => rec.GetString(i);

и используйте его так

rec.Get(GetString, index);
rec.Get(GetInt32, index);
0
ответ дан 2 December 2019 в 22:06
поделиться

Я не могу понять, зачем нужно усложнять весь этот процесс. Почему бы не сделать все просто и понятно и не использовать следующие строки кода:

Для типов значений, где null допустим, используйте int? iNullable = dr[ordinal] as int?;.

Для типов значений, где null недопустим, используйте int iNonNullable = dr[ordinal] as int? ?? default(int);.

Для ссылочных типов используйте string sValue = dr[ordinal] as string;.

Для тех, кто думает, что код не будет работать и что dr[ordinal] выбросит исключение для DBNull, приводим пример метода, который, получив корректную строку подключения, докажет концепцию.

private void Test()
{
  int? iTestA;
  int? iTestB;
  int iTestC;
  string sTestA;
  string sTestB;

  //Create connection
  using (SqlConnection oConnection = new SqlConnection(@""))
  {
    //Open connection
    oConnection.Open();

    //Create command
    using (SqlCommand oCommand = oConnection.CreateCommand())
    {
      //Set command text
      oCommand.CommandText = "SELECT null, 1, null, null, '1'";

      //Create reader
      using (SqlDataReader oReader = oCommand.ExecuteReader())
      {
        //Read the data
        oReader.Read();

        //Set the values
        iTestA = oReader[0] as int?;
        iTestB = oReader[1] as int?;
        iTestC = oReader[2] as int? ?? -1;
        sTestA = oReader[3] as string;
        sTestB = oReader[4] as string;
      }
    }
  }
}
1
ответ дан 2 December 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: