2011-02-09 41 views
4

我嘗試使用這種通用的方法擴展DataRow對象:通用領域的getter爲一個DataRow

public static T? Get<T>(this DataRow row, string field) where T : struct 
{ 
    if (row.IsNull(field)) 
    return default(T); 
    else 
    return (T)row[field]; 
} 

它的做工精細當T intdecimaldouble

但是當我嘗試用繩子用,我有這樣的錯誤:

「類型‘字符串’必須以一個 非空值類型在通用 類型或方法'System.Nullable'中使用它作爲參數'T'「

如何更正此問題?

我知道字符串不是一個結構,但如果字符串字段是DBNull,我不想返回null。

+1

你有約束T結構的目的嗎? – 2011-02-09 16:47:39

+0

問題是用T?,你不能有String?鍵入 – 2011-02-09 16:50:25

+0

是的原因,如果沒有這個約束,你有一個編譯錯誤,因爲你不能返回一個可爲空的類型(T?)。我知道這是問題,我不能使用字符串,因爲它不是一個結構。但是如果有人有想法? – 2011-02-09 16:52:14

回答

6

我認爲這是你想要什麼:

public static T? GetValue<T>(this DataRow row, string field) where T : struct 
{ 
    if (row.IsNull(field)) 
     return new T?(); 
    else 
     return (T?)row[field]; 
} 

public static T GetReference<T>(this DataRow row, string field) where T : class 
{ 
    if (row.IsNull(field)) 
     return default(T); 
    else 
     return (T)row[field]; 
} 
1

正如Wes指出的那樣,您的問題是對結構的限制。我希望擴展方法的工作沒有約束...

啊,我現在看到,你回來了T?嗯,我不知道,但你可以定義兩個變種的方法之一約束到struct,其他到class和返回T

+0

是的 - 嘗試刪除「其中T結構」 – Marco 2011-02-09 16:50:01

+1

@Marco:他也必須刪除可空行爲,儘管... – 2011-02-09 16:55:15

5

string不是struct,而是class。這就是錯誤信息告訴你的。只要刪除約束。

也許你想看看DataRowExtensions

1

您必須防止這種用繩子工作的明確條件:

where T : struct 

System.String是一類,而不是一個結構。如果您的目標是處理值類型和字符串,我會爲字符串創建一個單獨的方法,並將其單獨留給其他類型。

2

不幸的是,你不會是能夠通過使用泛型以獲取引用類型的可空返回類型和支持,除非你指定你想,當你撥打電話可空返回

public static T Get<T>(this DataRow row, string field) 
{ 
    if (row.IsNull(field)) 
     return default(T); 
    else 
     return (T)row[field]; 
} 

當你打電話

var id = dr.Get<int?>("user_id"); 

我沒有測試這個,只是把它扔在這裏。試一試。

編輯:

或者,如果你真的想要的值類型轉換成nullables,仍然能夠支持引用類型這樣的事情可能會奏效

public static object GetDr<T>(this DataRow row, string field) 
{ 
    // might want to throw some type checking to make 
    // sure row[field] is the same type as T 
    if (typeof(T).IsValueType) 
    { 
     Type nullableType = typeof(Nullable<>).MakeGenericType(typeof(T)); 
     if (row.IsNull(field)) 
      return Activator.CreateInstance(nullableType); 
     else 
      return Activator.CreateInstance(nullableType, new[] { row[field] }); 
    } 
    else 
    { 
     return row[field]; 
    } 
} 

但是,它會要求按照每種用法施用

var id = dr.Get<string>("username") as string; 
var id = (int?)dr.Get<int>("user_id"); 

然而,這不會像接受泛型類型參數中的可空類型那樣有效秒。

1

這樣的事情呢?不太一樣的例子,但相當可用於引用類型,可空值類型和非空的值類型一樣:

int v = row.Get<int>("vvv");    // throws if column is null 
int? w = row.Get<int?>("www");    // set to null if column is null 
int x = row.Get<int?>("xxx") ?? -1;  // set to -1 if column is null 
string y = row.Get<string>("yyy");   // set to null if column is null 
string z = row.Get<string>("zzz") ?? "" // set to "" if column is null 

// ... 

public static T Get<T>(this DataRow source, string columnName) 
{ 
    if (source == null) 
     throw new ArgumentNullException("source"); 

    if (columnName == null) 
     throw new ArgumentNullException("columnName"); 

    if (columnName.Length < 1) 
     throw new ArgumentException("Name cannot be empty.", "columnName"); 

    if (source.IsNull(columnName)) 
    { 
     T defaultValue = default(T); 
     if (defaultValue == null) 
      return defaultValue; 
    } 

    // throws if the column is null and T is a non-nullable value type 
    return (T)source[columnName]; 
} 
2
ds.Tables[7].Rows.OfType<DataRow>().ToList().ForEach(f => tempList.Add(new MyEntity 
{ 
    Id = int.Parse(f.ItemArray[0].ToString()), 
    Title = f.ItemArray[1].ToString() 
}));