2

Here is my code :

object w = 44;
var k1 = (w is double
       ? ((Convert.ToSingle(w)))
       : ((unchecked((uint)Convert.ToInt64(w)))));
if (w is double)
{
    w = 22;
}

The result is that k1 = 44.0 and w == 44;

I wonder why the results is different!

Let's assume w is double, in this case k1 should be 44.0 and w should be 22.

Now let's assume w is not double, in this case k1 should be 44 and w should be 44.

What is the problem !?

Sterling Archer
  • 22,070
  • 18
  • 81
  • 118
Mohsen Sarkar
  • 5,910
  • 7
  • 47
  • 86
  • which environment you are using? – hanskishore Dec 20 '13 at 19:05
  • 2
    I *think* your problem is that you can't use `? :` syntax to return two different types. `k1` is inferred to be a single because the first case of your `if` returns a single and the `uint` returned from the second part is silently converted. – Matt Burland Dec 20 '13 at 19:06
  • 2
    Also, the dead give away is if you test the type of `k1`, even just hovering over it in Visual Studio will tell you it's a `float`. – Matt Burland Dec 20 '13 at 19:08
  • 3
    Another way to see what's happening, try `var foo = true ? "hi" : 1;` Note this will give you a compiler error because it can't convert 1 to a string implicitly. – Matt Burland Dec 20 '13 at 19:11

3 Answers3

10

The type of the conditional expression used to initialize k1 is the same no matter what type w turns out to be. The compiler has to determine the conditional expression type at compile time based on the types of the 2 possible values.

cond ? float: uint

These types are not the same but uint can implicitly convert to float hence the compiler chooses that as the return type

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
2

w is an int (44). The type of your ternary expression is a float, therefore k1 is float.

Therefore the 'false' branch of your ternary is executed and k1 is:

k1 = (float)((unchecked((uint)Convert.ToInt64(w)))))
Lee
  • 142,018
  • 20
  • 234
  • 287
1

Observe:

object w = 44;
object k1 = (w is double ? (object)((Convert.ToSingle(w))) : (object)((unchecked((uint)Convert.ToInt64(w)))));
if (w is double)
{
    w = 22;
}
Console.WriteLine("{0}, {1}", w.GetType(), k1.GetType());

Console.ReadLine();

Magic, it now tells you it's an uint :-)

The problem is the implicit conversion from uint to float, which is because of the ternary condition.

atlaste
  • 30,418
  • 3
  • 57
  • 87