Generic decimal can't cast from double

By : bto.rdz
Source: Stackoverflow.com
Question!

I don't see why this is not working, I can do a direct cast from double to decimal with no problem, but unexpectedly I can't do this cast if it is inside a generic class, this snippet explains it better:

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 was unhandled by user code HResult=-2147467262 Message=Specified cast is not valid. Source=Wpf StackTrace: at Wpf.TestCollection`1.Add(Object value) in C:\Users\btord\Source\Repos\Live-Charts\Examples\Wpf\JimmyTheTestsGuy.xaml.cs:line 15 at Wpf.JimmyTheTestsGuy..ctor() in C:\Users\btord\Source\Repos\Live-Charts\Examples\Wpf\JimmyTheTestsGuy.xaml.cs:line 35 at Wpf.MainWindow..ctor() in C:\Users\btord\Source\Repos\Live-Charts\Examples\Wpf\MainWindow.xaml.cs:line 56 InnerException:

By : bto.rdz


Answers

It fails due to the exact same reason why the following fails:

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

The reason being that a boxed value can only be unboxed to its real type. In your case your are boxing a double and trying to unbox it to a decimal. That is not allowed.

I'd push back on the whole design. You have a generic collection of Ts. Your Add method should simply accept Ts and let the caller carry the burden of converting to the right type. If that's not a valid solution then get rid of generics all together and simply implement a collection of objects.

By : InBetween


You could use Convert.ChangeType for that:

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

See the fiddle: https://dotnetfiddle.net/0Tfgyz



If you need object insead of T you can use dynamic in your Add method.

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


This video can help you solving your question :)
By: admin