0

Firstly, this question is not a duplicate of this question. Other than the title it has absolutely nothing in common.

Now...

In C#, consider the following situations:

int i = (int)10.0;

const double D = 10.0;
float f = (float)d; 

enum Foo : int
{
    FIRST_ITEM = 0
}
int i = (int)Foo.FIRST_ITEM;

In which of these situations does the typecasting happen at runtime? I currently feel like obsessing over my program's performance a little, and was wondering whether this would have any (no matter how small) influence.

Community
  • 1
  • 1
Lee White
  • 3,649
  • 8
  • 37
  • 62
  • possible duplicate of [Compile-time and runtime casting c#](http://stackoverflow.com/questions/4499528/compile-time-and-runtime-casting-c-sharp) – Tim Schmelter Apr 24 '13 at 12:39
  • Premature micro-optimization is a root of all evil. Build a working app with clear architecture, run a profiler over it and optimize only the parts that are worth optimizing. – alex Apr 24 '13 at 12:39
  • 1
    It's compile-time for constants. If you want to know for sure, use `Reflector` to inspect the output code. – Matthew Watson Apr 24 '13 at 12:41
  • Thanks, @MatthewWatson. To the people tagging this as a duplicate: Please check the contents of questions/answers too; not just the titles. – Lee White Apr 24 '13 at 12:42
  • That does entirely depend on your compiler. What environment are you using and what compilation flags? In general most "casts" for compile time value-constants are done at statically. To those screaming duplicate, note that he asked when the actual cast is done, not when the check whether or not the actual cast is valid is done. – flindeberg Apr 24 '13 at 12:44

2 Answers2

4

In short, Linqpad does a lot statically, which means that when compiling with either the ms or mono compiler with optimization flags on they should at least not do less statically.

When using Linqpad I get with the following C# code:

void Main()
{
  int i = (int)10.0;

  const double D = 10.0;
  float f = (float)D; 

  int h = (int) Foo.Bar;
}

public enum Foo : int {
  Bar = 0
}

I get the following IL:

IL_0001:  ldc.i4.s    0A // load int8 0A (ie 10 dec)
IL_0003:  stloc.0     // assign i
IL_0004:  ldc.r4      00 00 20 41 // FLOAT! not double
IL_0009:  stloc.1     // assign f
IL_000A:  ldc.i4.0    // load int32 0 (due to Foo : int(32))
IL_000B:  stloc.2     // assign h
flindeberg
  • 4,887
  • 1
  • 24
  • 37
2

Casts from constants are done at compile time.

To prove this, you can use .Net Reflector to inspect the generated code.

For example, this code:

static void Main()
{
    int i = (int) 10.5;
    const double d = 10.0;
    float f = (float)d;

    Console.WriteLine(i);
    Console.WriteLine(f);
}

Produces:

private static void Main()
{
    int i = 0xa;
    float f = 10f;
    Console.WriteLine(i);
    Console.WriteLine(f);
}

Or as IL:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] int32 i,
        [1] float32 f)
    L_0000: ldc.i4.s 0xa
    L_0002: stloc.0 
    L_0003: ldc.r4 10
    L_0008: stloc.1 
    L_0009: ldloc.0 
    L_000a: call void [mscorlib]System.Console::WriteLine(int32)
    L_000f: ldloc.1 
    L_0010: call void [mscorlib]System.Console::WriteLine(float32)
    L_0015: ret 
}

As you can see, no runtime casts are happening. It's the same for release OR debug builds.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276