16

before judging that this question is already answered, please read the description. I have this simple code below:

Dictionary<string, object> d = new Dictionary<string, object>();

d.Add("key" , 30d);

System.Diagnostics.Debug.WriteLine($" TYPE OF OBJECT IS  \"{d["key"].GetType()}\"");

netPlannedHours = (float)d["key"];         ---> **Line of Interest**

When i execute this i get:

TYPE OF OBJECT IS "System.Double" Exception thrown: 'System.InvalidCastException' in DevOpsAutomatedReporting.dll Unable to cast object of type 'System.Double' to type 'System.Single'.

The exception is caused by the last line tagged "Line of interest". I can't really understand why the last line is causing this as the type of the object is inferred to be "System.Double" at runtime so it should've had cast it to a float but it doesn't. An interesting point is that if i replace the last line ("Line of interest") with either of the following two lines of code it successfully converts the double to float

// Cast the double object to double again and then to float **WORKS**
netPlannedHours = (float)(double)d["key"];
  
// Convert to float using "Convert.ToSingle()"  **WORKS**
netPlannedHours = Convert.ToSingle(d["key"]);
GEOCHET
  • 21,119
  • 15
  • 74
  • 98
With A SpiRIT
  • 478
  • 3
  • 6
  • 17
  • Possible duplicate of [Cast object containing int to float results in InvalidCastException](https://stackoverflow.com/questions/24447387/cast-object-containing-int-to-float-results-in-invalidcastexception) – GSerg Jul 19 '19 at 07:52
  • Possible duplicate of [Casting object to int throws InvalidCastException in C#](https://stackoverflow.com/q/39891504/11683) – GSerg Jul 19 '19 at 07:53
  • Possible duplicate of [Why does (int)(object)10m throw “Specified cast is not valid” exception?](https://stackoverflow.com/q/3953391/11683) – GSerg Jul 19 '19 at 07:53
  • Possible duplicate of [Why can't I unbox an int as a decimal?](https://stackoverflow.com/q/1085097/11683) – GSerg Jul 19 '19 at 07:55

3 Answers3

19

When you add to the dictionary your double will be boxed, as the dictionary is mapping a string to an object.

When you unbox you must cast to the underlying type. In your case that underlying type is a double, so the cast to float will fail.

You can get around this by using Convert.ToSingle

netPlannedHours = Convert.ToSingle(d["key"])

This method will work out the underlying type and can do the conversion, at the expense of a performance hit when working out the type conversions.

Sean
  • 60,939
  • 11
  • 97
  • 136
7

I had a similar problem today with my SQL entity mapped as "float" and my .Net entity mapped as "float". I kept the SQL mapping, though changed the .Net types to "double".

The ADO.NET SQL Server Data Type Mappings documentation presents a table of the correct mapping for all types.

0xced
  • 25,219
  • 10
  • 103
  • 255
Alan Hord
  • 71
  • 1
  • 4
  • This is a very good solution when you're mapping SQL entity with .Net entity so if you're experiencing the same problem check it out – Martin Kinuthia Dec 01 '21 at 23:34
3

I recently had a similar problem. In my case the problem was with the data types between SQL and C#. The real data type in SQL Server is equivalent to Single in C#. I quote the original answer

"SQL Server real is equivalent to C# Single and SQL server float is equivalent to C# Double." System.InvalidCastException: 'Unable to cast object of type 'System.Double' to type 'System.Single'.'

I hope it can be useful to other people

Laurien
  • 106
  • 1
  • 3