通用十进制不能从double转换

时间:2016-09-20 18:29:59

标签: c# generics casting

我不明白为什么这不起作用,我可以毫无问题地从double直接演员到decimal,但出乎意料的是,如果它在通用类,这个片段更好地解释了它:

public class TestCollection<T>
{
    public void Add(object value)
    {
        //When T is decimal, then I get 
        // System.InvalidCastException
        var t = (T) value;
    }
}

public void Main ()
{
    var t = new TestCollection<decimal> ();
    double doub = 10;

    var decim = (decimal) doub; //Works!       
    t.Add(doub);                //throws!
}
  

System.InvalidCastException未被用户代码处理     的HResult = -2147467262     消息=指定的强制转换无效。     来源= WPF     堆栈跟踪:          在Wpf.TestCollection`1.Add(对象值)C:\ Users \ btord \ Source \ Repos \ Live-Charts \ Examples \ Wpf \ JimmyTheTestsGuy.xaml.cs:第15行          在Wpf.JimmyTheTestsGuy..ctor()中的C:\ Users \ btord \ Source \ Repos \ Live-Charts \ Examples \ Wpf \ JimmyTheTestsGuy.xaml.cs:第35行          在C:\ Users \ btord \ Source \ Repos \ Live-Charts \ Examples \ Wpf \ MainWindow.xaml.cs中的Wpf.MainWindow..ctor():第56行     InnerException:

3 个答案:

答案 0 :(得分:5)

由于以下原因失败的原因完全相同:

short s = 1;
object o = s;
var i = (int)o; //Runtime error

原因是盒装值只能拆分为真实类型。在您的情况下,您正在装箱double并尝试将其取消装箱到decimal。这是不允许的。

我会推翻整个设计。您有一个T的通用集合。您的Add方法应该只接受T并让调用者承担转换为正确类型的负担。如果那不是一个有效的解决方案,那么一起摆脱泛型并简单地实现一组对象。

答案 1 :(得分:5)

您可以使用Convert.ChangeType

public void Add(object value)
{
    var t = Convert.ChangeType(value, typeof(T));
}

请参阅小提琴:https://dotnetfiddle.net/0Tfgyz

答案 2 :(得分:1)

如果你需要T的对象插入,你可以在Add方法中使用dynamic。

 public void Add(object value)
 {
      //When T is decimal, then I get 
      // System.InvalidCastException
      dynamic t1 = value;
      var t = (T)t1;
 }