12

I saw a code like this:

private readonly object[] m_Values = { (int)0, (int)0 };

What's the idea to cast 0 to int? Isn't it int by 'default' ?

Dimitar Tsonev
  • 3,711
  • 5
  • 40
  • 70
  • 10
    Yes it is, that looks a little pointless, though my head compiler could be wrong. – Adam Houldsworth May 09 '13 at 07:21
  • 24
    This may come as a shock to many people but sometimes programmers do weird, unnecessary things ;) – Captain Kenpachi May 09 '13 at 07:28
  • Maybe the program, or that line in the program, was produced by a program? A translation from another language, or a template-driven interface-creator or something? That program maybe always places a cast on literals as part of the way it operates. – RenniePet May 09 '13 at 07:35
  • 2
    It's very likely just for readability. I assume at some point that m_Values will hold non-integer values, so when you see that line you understand the initial state. – Murkaeus May 09 '13 at 07:43

3 Answers3

18

It is not necessary. I'd assume the programmer got bitten before. I'll post it as a puzzler, which overload will be called in this program?

using System;

class Program {
    static void Main(string[] args) {
        Foo.Bar(0);
        Console.ReadLine();
    }
}

class Foo {
    public static void Bar(byte arg)  { Console.WriteLine("byte overload"); }
    public static void Bar(short arg) { Console.WriteLine("short overload"); }
    public static void Bar(long arg)  { Console.WriteLine("long overload"); }
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 4
    +1 Interesting. Are you going to supply the "why" behind the result? I'm assuming behind the overload resolution there is a path that says what the smallest encompassing type is for a given literal if the literal cannot go into it's defined default type. – Adam Houldsworth May 09 '13 at 10:39
  • Eh, I got the right answer, but I can't be sure if I my reasoning is correct. Could you illustrate why it picks the overload it does? Ta pal – Binary Worrier May 09 '13 at 10:44
  • 5
    Sorry, I can't supply the "why", this makes no sense to me ;) Notable is that VB will pick the long overload. It's a real problem with the EncoderParameter class, it doesn't have a constructor that takes an int. Just another tidbit of voodoo I stuffed in a corner of the brain to watch out for. But otherwise illustrative how somebody could end up thinking that the type of 0 is not necessarily *int*. – Hans Passant May 09 '13 at 11:09
  • 2
    I got the wrong answer. I found it interesting that "int zero = 0; Foo.Bar(zero);" got the answer I was expecting, but "const int zero = 0; Foo.Bar(zero);" got the same answer as the puzzler. – Chuu May 09 '13 at 19:15
  • `var zero = 0; Foo.Bar(zero);` gives same answer as `int zero = 0; Foo.Bar(zero);` but different from `Foo.Bar((int)0);` – basarat May 21 '13 at 03:13
  • @Chuu `Foo.Bar(0)` means 0 is `const int` instead of `int`. It makes sense now. `const inst` goes to the smallest size the compiler can fix that int into i.e `byte` in case of `0`. Whereas `int` will got it's own size or larger i.e. `long` – basarat May 21 '13 at 03:15
  • Question related to this answer: [Why can I pass 1 as a short, but not the int variable i?](http://stackoverflow.com/questions/11432508/why-can-i-pass-1-as-a-short-but-not-the-int-variable-i) which explains why a constant integer is convertible to shorter integer types, but not why overload resolution prefers it. I would have expended an ambiguous match compiler error for this. – CodesInChaos Jun 07 '13 at 18:26
  • 6
    The reasoning is: a constant integer is *implicitly convertible* to any integral type that it will fit into, therefore all three methods are *applicable*. We must now determine which of the three applicable methods is *best*. It is the one with the most *specific* parameter type. Type X is more specific than type Y if it is true that "all X can be converted to Y but not all Y can be converted to X". That is, Giraffe is more specific than Animal because all Giraffes are Animals but not vice versa. byte is more specific than either short or long, so it wins. – Eric Lippert May 26 '14 at 00:18
  • 2
    @Eric - biblical section 2.4.4.2: "Integer literals are used to write values of types int, uint, long, and ulong". There's no giraffe that looks like a byte in that chapter. You can call it a feature, everybody is completely confounded about it anyway. Well, there's a rule you can add to your code analysis tool. – Hans Passant May 26 '14 at 00:32
5

I think it is pointless to have it like that, but the only place I think that can be useful is where the original coder wanted to prevent this value to be casted to other data type. Consider the example:

object[] m_Values = { (int)0, (int)0 };
Int16 item = (Int16) m_Values[0];

or

object[] m_Values = { (int)0, (int)0 };
Int64 item = (Int64)m_Values[0];

The above would result in

Specified cast is not valid.

but following would work:

object[] m_Values = { (int)0, (int)0 };
int item = (int)m_Values[0];
Habib
  • 219,104
  • 29
  • 407
  • 436
  • 1
    Although that is a valid example, it only essentially creates an annoyance at run-time. Plus, the explicit casting of the literal `0` isn't necessary to enforce this same situation. – Adam Houldsworth May 09 '13 at 07:42
0

C# defaults to Int32 when you declare an integer literal without supplying a type hint (as long as the literal fits into an Int32, otherwise it will go to Int64). From here:

In C#, literal values receive a type from the compiler. You can specify how a numeric literal should be typed by appending a letter to the end of the number. For example, to specify that the value 4.56 should be treated as a float, append an "f" or "F" after the number

Vyacheslav Volkov
  • 4,592
  • 1
  • 20
  • 20
  • If it were this simple, @HansPassant's puzzler wouldn't be a puzzle and VB's behaviour would occur... – Mark Hurd May 16 '13 at 02:09
  • Function: `void f(byte b) { }` Legal call: `f(0);` - So if C# defaults to `Int32`, and `Int32` cannot implicitly cast to `byte`, then why is it a legal call? :) – Timothy Shields Jun 07 '13 at 17:57
  • @TimothyShields [Why can I pass 1 as a short, but not the int variable i?](http://stackoverflow.com/questions/11432508/why-can-i-pass-1-as-a-short-but-not-the-int-variable-i) – CodesInChaos Jun 07 '13 at 18:28