2013-11-22 73 views
4

爲什麼這項工作:通用鑄造

decimal dec = new Decimal(33); 
double dd = (double) dec; 
Console.WriteLine(dd); 

但不是這樣的:

decimal dec = new Decimal(33); 
object o = (object)dec; 
double dd = (double) o; 
Console.WriteLine(dd); 

第二個例子拋出:

System.InvalidCastException:指定投無效。

這個問題來自一個情況我有一個通用的方法

public T GetValue(string q) 

,從數據源獲取的值。這些值的類型是未知的,但該方法假定它可以將值轉換爲T.有時,該值將爲對象​​{decimal},T將爲double,在這種情況下,將拋出InvalidCastException。但原則上這不應該是一個問題,因爲值是一個十進制數(雖然被對象裝箱),可以將其加倍。

我該如何處理這個問題?

回答

10

您只能將盒裝值類型返回以確定類型已裝箱。無論是從盒裝類型還是從您正在投射的內容進行隱式或顯式轉換都無關緊要 - 您仍然必須投入盒裝類型(爲了取消箱),然後從那裏拿走。

在這個例子中,這意味着兩個連續的石膏:

double dd = (double) (decimal) o; 

或者使用Convert方法:

double dd = Convert.ToDouble(o); 

當然,這不會爲您的實際使用情況下做的,因爲你不能立即從泛型類型參數變爲ToDouble。但只要目標類型爲IConvertible,你可以這樣做:

double dd = (double)Convert.ChangeType(o, typeof(double)); 

在泛型類型參數T可以取代double

3

後者不起作用,因爲十進制值被裝箱到一個對象中。這意味着獲得值回你必須拆箱首先使用的相同的語法鑄造,所以你必須這樣做,在2個步驟是這樣的:

double dd = (double) (decimal) o; 

注意,第一(decimal)是拆箱時,(double)正在鑄造。

2

這可以用Convert.ChangeType做到:

class Program 
{ 
    static void Main(string[] args) 
    { 
     decimal dec = new Decimal(33); 
     object o = (object)dec; 
     double dd = GetValue<double>(o); 
     Console.WriteLine(dd); 
    } 

    static T GetValue<T>(object val) 
    { 
     return (T)Convert.ChangeType(val, typeof(T)); 
    } 
} 

您的代碼不工作一直深受其他人對這個職位解釋原因。