2013-10-07 121 views
2

我想創建一個這樣的泛型函數,我打算實例化基本類型,大多數是DateTime,int和字符串。強制C#泛型類型的任意函數

static T MyParameter<T>(string value, T defaultValue) 
{ 
    return value.StartsWith("$$") ? defaultValue : T.Parse(value); 
} 

這不會編譯,因爲不能保證T會有「解析」。

有沒有一種「直接」的方式來實現它? (我的意思是,避免反思或代表做骯髒的工作)。

我找不到任何約束T會做的伎倆。

+0

恐怕沒有。 – MarcinJuraszek

+1

我的一般做法是將'T'約束爲'IConverible',並使用'Convert.ChangeType'並將其轉換爲T來處理。但是,如果您的價值以$$開頭,除非您剝離美元符號,否則幾乎總是無法解析。 – vcsjones

+0

@vcsjones我認爲這就是爲什麼當'value'以'$$'開始時他返回'defaultValue'的原因。 – MarcinJuraszek

回答

6

你可以在分析方法通過爲通用情況:

static T MyParameter<T>(string value, T defaultValue, Func<string, T> parse) 
{ 
    return value.StartsWith("$$") ? defaultValue : parse(value); 
} 

但爲了方便起見,你可能要爲您計劃使用的最常見類型的提供重載:

static int MyParameter(string value, int defaultValue) 
{ 
    return MyParameter(value, defaultValue, int.Parse); 
} 
static DateTime MyParameter(string value, DateTime defaultValue) 
{ 
    return MyParameter(value, defaultValue, DateTime.Parse); 
} 
static string MyParameter(string value, string defaultValue) 
{ 
    return MyParameter(value, defaultValue, x => x); 
} 

如果你真的不喜歡這樣,你可以使用反射,但我不會推薦它:

static T MyParameter<T>(string value, T defaultValue) 
{ 
    if (value.StartsWith("$$")) 
    { 
     return defaultValue 
    } 

    var method = typeof(T).GetMethod("Parse", new[] { typeof(string) }); 
    return (T)method.Invoke(null, new[] { value }); 
} 
+0

注意:如果您將'method'緩存在字典中,則每個值爲T的反射實際上可以更快一些。 (更多的時間用於驗證* right *方法)當然,基本類型都實現'IConvertible'。 – 2013-10-08 13:35:28

1

這應該這樣做:

static T MyParameter<T>(string value, T defaultValue) 
{ 
    return (T) (value.StartsWith("$$") ? defaultValue : Convert.ChangeType(value, typeof (T))); 
} 
2

在泛型上使用約束怎麼樣?

http://msdn.microsoft.com/en-us/library/d5x73970.aspx

所以,你的方法就變成了:

static T MyParameter<T>(string value, T defaultValue) where T : IParseable 
{ 
    return (T)(value.StartsWith("$$") ? defaultValue : defaultValue.Parse(value)); 
} 

當然,這意味着使用的所有類型必須實現IParseable。

+0

這是正確的方法。基本上,您需要使用該類型的協方差來確保它符合您嘗試調用的內容。 – Alex

+0

這實際上不會編譯。 ** 1)**您試圖在'T',** 2)**上靜態調用'Parse',除非'IParseable'是通用的(例如'where T:IParseable '),那麼返回值'Parse'可以在沒有強制轉換的情況下返回,並且** 3)**即使您修復了這些問題,您仍然無法使用內置數據類型('int','DateTime',''字符串')由.NET提供,因爲它們不實現自定義'IParseable'接口。 –

+0

是的,你說得對。我修復了#1和#2。 #3,你完全正確。這是這個代碼的問題。你基本上必須爲所有煩人的基本數據類型編寫包裝。 – Zippit