using System;
static class Utility<T, TReturn>
{
public static TReturn Change(T arg)
{
// is there any solution to do this type casting but without dynamic keyword?
return (TReturn)(arg as dynamic);
}
}
class Program
{
static void Main(string[] args)
{
int i = 100;
try
{
short s = Utility<int,short>.Change(i);
Console.WriteLine(s);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
回答
絕對如此。在這裏,你去...
static class Utility<T, TReturn> {
public static TReturn Change(T arg) {
return (TReturn)Convert.ChangeType(arg, typeof(TReturn));
}
}
static class Utility<T, TReturn>
where T : TReturn
{
public static TReturn Change(T arg)
{
return (TReturn) arg;
}
}
您的代碼不適用於提問者提供的代碼。 'int'不是'short'。提問者正在尋找一種類型轉換,而不僅僅是一個簡單的轉換。 – mattmc3 2010-10-12 04:05:32
您可以添加約束T : TReturn
。但是這不適用於您的值類型:
using System;
static class Utility<T, TReturn>
where T : TReturn
{
public static TReturn Change(T arg)
{
return (TReturn)(arg);
}
}
class Program
{
static void Main(string[] args)
{
string i = "100";
try
{
object s = Utility<string, object>.Change(i);
Console.WriteLine(s);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
即使簡單:
static class Utility<T, TReturn>
{
static TReturn Change(T arg, Converter<TReturn, T> convert)
{
System.Diagnostics.Debug.Assert(arg != null);
return convert(arg);
}
}
或者試試下面的,如果你不能接受一個自定義轉換器的委託:
static class Utility<T, TReturn>
{
static TReturn Change(T arg)
{
return (TReturn) System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertTo(arg, typeof(TReturn));
}
}
使用Convert.ChangeType(object,Type)
的解決方案是不與使用動態調度的方法一樣靈活。主要是因爲很少有類型實現IConvertible。例如,假設你想從一個值類型轉換爲它的可空值類型,這會拋出一個異常。 下面是一個例子::
Converter<short, short?> test1 = @short =>(short?)Convert.ChangeType(@short, typeof(short?));
test1(5);
這是不通用的代碼,但它仍然證明了它會炸掉點。更糟糕的是,在這種情況下,簡單的演員實際上工作。你真正需要的是一個「智能」轉換器。
首先,我們需要定義您願意接受的懲罰。 如果您準備好調用DLR,這可能是您最安全的選擇。該代碼幾乎保證做正確的事情。由於呼叫站點被緩存,如果調用足夠的話,它實際上會表現得非常好。
我不會假裝沒有簡單的解決方案。你最好的選擇是開始考慮限制功能的範圍或範圍。例如,如果您將TResult的限制添加爲IConvertible,那麼您不必擔心可空。儘管如此,它仍然會炸燬Enums。
你可以做的是建立一個轉換器委託來處理返回類型的工作。然後按返回類型緩存它。您將始終禁用值類型,但其內存密集程度要低很多,因此必須緩存該方法調用的每個配對的委託。該邏輯基本上必須處理幾種情況::
If(TReturn.IsValueType)
{
If(TReturn.IsEnum) Cast to Enum base type using Convert.To(base), then to Enum.
If(TReturn.IsNullable<>) Cast to Nullable<> generic type using Convert.To(base), then to Nullable<T>
If(TReturn.ISNullableEnum) Cast to Enum base type using Convert.To(base), then to Nullable enum.
Otherwise, just call Convert.To(TReturn) if that method exists.
}
If it's Iconvertible try calling Convert.ChangeType(object,Type) and cast as TReturn.
If no method has been found yet, try doing an explicit cast TReturn.
這對實現轉換運算符的代碼仍然失敗,這不是IConvertible。但它非常接近你想要的。要添加對轉換運算符的支持,您必須爲每個TInput,TReturn緩存不同的委託。這是一個更大的混亂,因爲你現在開始擔心在某些情況下試圖不加框,在那裏它更容易調用拳擊方法,並且需要很多工作才能得到正確的結果。除非這是必須成爲代碼庫的一部分,否則我會避免使用這種清理工具,return (TReturn)(value as dynamic)
。
我爲我的數據庫層做了這樣的事情,我目前正在嘗試用更簡單和不那麼痛苦的動態代碼替換.NET 3.5代碼。 上述可能會比DLR代碼略微(並且略微)執行得更好,並且不會像DLR呼叫那樣安全或穩健。
謝謝。很好的解釋。 – xport 2010-10-12 05:50:10
- 1. 使用泛型進行類型轉換
- 2. 我可以@注入泛型類型嗎?
- 3. 我們可以有一個泛型的類類型嗎?
- 4. 動態設置泛型類型參數
- 5. 創建動態泛型類型參數
- 6. 基於泛型參數的java泛型類型推斷
- 7. 基於泛型參數類型的類型推斷(德爾福)
- 8. 當前類的類型可以用作泛型類型參數的值嗎?
- 9. 我們可以使用返回類型與輸入參數類型相同的泛型函數嗎?
- 10. 我們可以使用工會進行類型轉換嗎?
- 11. 與類型的動態計數泛型類型參數
- 12. 使用泛型類型參數類
- 13. 我可以使用反射類型作爲類型參數嗎?
- 14. 傳遞類型參數動態地泛型類型
- 15. 我們可以推斷泛型輸出類型嗎?
- 16. 泛型類型參數不是類型?
- 17. 泛型類型參數和類型
- 18. 我們可以在C#中的泛型中寫List作爲類型參數嗎?
- 19. 使用泛型類型的參數化構造函數基類
- 20. 從基類型的行動泛型
- 21. Java泛型類型參數
- 22. 泛型類型參數
- 23. C#類型轉換爲泛型參數
- 24. 使用泛型將類型對象類型轉換爲泛型類型
- 25. 泛型類型作爲泛型類型參數
- 26. 帶泛型類型參數的網絡泛型類型
- 27. C#將泛型類型作爲泛型類型參數傳遞?
- 28. (開放泛型類型)泛型類型,沒有指定參數
- 29. 泛型 - 使用GetRuntimeMethod與類型參數
- 30. 我們如何使用Java中的泛型類型和基本類型工作
除了演員之外,你還想達到什麼目的?你是否想避免爲上面的例子寫'(short)i'? – shahkalpesh 2010-10-12 03:59:18
這只是一個簡單的例子。 – xport 2010-10-12 04:03:12