2010-04-06 77 views
4

我有類似下面的擴展方法:如何指定泛型方法類型參數部分

public static T GetValueAs<T, R>(this IDictionary<string, R> dictionary, string fieldName) 
    where T : R 
{ 
    R value; 
    if (!dictionary.TryGetValue(fieldName, out value)) 
     return default(T); 

    return (T)value; 
} 

目前,我可以通過以下方式來使用它:

var dictionary = new Dictionary<string, object>(); 
    //... 
    var list = dictionary.GetValueAs<List<int>, object>("A"); // this may throw ClassCastException - this is expected behavior; 

它工作得很好,但第二個類型參數真的很煩人。是否有可能在C#4.0中重寫GetValueAs是這樣一種方式,該方法仍然適用於不同類型的字串鍵控字典,並且不需要在調用代碼中指定第二個類型參數,即使用

var list = dictionary.GetValueAs<List<int>>("A"); 
或至少類似的
var list = dictionary.GetValueAs<List<int>, ?>("A"); 
代替
var list = dictionary.GetValueAs<List<int>, object>("A"); 

+1

因此,基本上你想要做的是從'字典'推斷'R'的類型,而不是指定它? – 2010-04-06 12:37:23

+0

是的,這就是我想要的。 – DNNX 2010-04-06 13:14:14

回答

1

只要您只使用它的對象字典,你可以約束噸至是引用類型,使投有效:

public static T GetValueAs<T>(this IDictionary<string, object> dictionary, string fieldName) 
    where T : class { 
    object value; 
    if (!dictionary.TryGetValue(fieldName, out value)) 
    return default(T); 

    return (T)value; 
} 

但是這可能不是你想。請注意,C#版本4 doesn't solve your problem要麼。

+0

你是對的,那不是我想要的。正如我所說的,我想在不同類型的字符串鍵詞典上使用這種方法,即不僅在IDictonary <字符串,對象>上,而且在IDictonary ,IDictonary <字符串,IEnumerable >等。 – DNNX 2010-04-06 13:42:19

+0

C#不是正確的語言,靜態類型檢查是King。尋找像Python或Ruby這樣的動態語言。或者是一種通過類型擦除實現泛型的語言,如Java。 – 2010-04-06 13:48:59

0

什麼

public static void GetValueAs<T, R>(this IDictionary<string, R> dictionary, string fieldName, out T value) 
    where T : R 
{ 
    value = default(T); 
    dictionary.TryGetValue(fieldName, out value) 
} 

然後,你可以這樣做

List<int> list; 
dictionary.GetValueAs("fieldName", out list); 

基本上有它infere是你有什麼噸至具有類型T的參數的東西。

編輯

也許一個更好的方式是

public static T GetValueAs<T, R>(
    this IDictionary<string, R> dictionary, 
    string fieldName, 
    T defaultValue) 
    where T : R 
{ 
    R value = default(R); 
    return dictionary.TryGetValue(fieldName, out value) ? 
     (T)value : defaultValue; 
} 

然後你可以使用var和鏈,這讓你能夠控制的默認值是什麼的能力。

var x = dict.GetValueAs("A", new Dictionary<string,int>).GetValueAs("B", default(int)); 
+0

謝謝你的建議,男人。我已經考慮過這種方法。我覺得這不是很優雅。 「連鎖調用」是不可能的,例如(dict.GetValueAs >(「A」)。GetValueAs (「B」)),使用var關鍵字是不可能的(var x = dict.GetValueAs (「C」)) ),不可能直接從字典返回值(返回dict.GetValueAs (「C」);)等 – DNNX 2010-04-06 15:55:59

+0

另一種選擇是返回值,但也傳遞一個值只是爲了獲得類型如var x = dict.GetValueAs(「A」,新詞典())。GetValueAs(「B」,default(int));也醜陋,但我能想到的唯一的其他方式。 – juharr 2010-04-08 23:19:12

0

也許你可以讓自己的字典類此行爲:

public class CastableDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
     { 
      public TOut GetValueAs<TOut>(TKey key) where TOut : TValue 
      { 
       TValue result; 
       if (this.TryGetValue(key, out result)) 
       { 
        return (TOut)result; 
       } 
       return default(TOut); 
      } 
     } 



var d = new CastableDictionary<string, object>(); 

     d.Add("A", 1); 

     d.Add("B", new List<int>() { 1, 2, 3}); 

     var a = d.GetValueAs<int>("A"); // = 1 

     var b = d.GetValueAs<List<int>>("B"); //= 1, 2, 3 

可能不希望這樣做無論是乾草的嗡嗡聲。

+0

好的解決方案。但是,我想使用內置的.NET IDictionary的擴展方法,因爲我指的是返回IDictionaries的外部代碼。 – DNNX 2010-04-06 15:59:08

0

我錯過了什麼,當然這是你想要的嗎?也許你需要更好的轉換,但是對於一般的演員,這應該這樣做:

public static T getValueAs<T>(this IDictionary dict, string key) 
{    
    try 
    { 
     return (T)dict[key]; 
    } catch 
    { 
     return default(T); 
    }    
} 

使用時只要

MyDictionary.getValueAs<Int32>("hello"); 

隨着IDictionary的,你不需要爲鍵和值指定類型,然而,隨着字典繼承此功能,無論您的字典是如何創建的。你甚至可以使用對象而不是字符串作爲鍵。

相關問題