【问题标题】:C#: Does typecasting of constants happen at runtime?C#:常量的类型转换是否在运行时发生?
【发布时间】:2013-04-24 12:37:03
【问题描述】:

首先,这个问题不是this question 的重复。除了标题之外,它绝对没有任何共同点。

现在...

在 C# 中,考虑以下情况:

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;

在哪些情况下类型转换会在运行时发生?目前,我对我的程序的性能有点着迷,想知道这是否会产生任何(无论多么小)影响。

【问题讨论】:

  • 过早的微优化是万恶之源。构建一个具有清晰架构的工作应用程序,在其上运行分析器并仅优化值得优化的部分。
  • 这是常量的编译时间。如果您想确定,请使用Reflector 检查输出代码。
  • 谢谢,@MatthewWatson。对于将其标记为重复的人:请也检查问题/答案的内容;不仅仅是标题。
  • 这完全取决于你的编译器。您正在使用什么环境以及什么编译标志?通常,编译时值常量的大多数“强制转换”都是静态完成的。对于那些尖叫的复制品,请注意他问的是实际演员表何时完成,而不是检查实际演员表是否有效的时间。

标签: c# casting enums runtime compile-time


【解决方案1】:

简而言之,Linqpad 做了很多静态操作,这意味着当使用带有优化标志的 ms 或 mono 编译器进行编译时,它们至少不应减少静态操作。

使用 Linqpad 时,我得到以下 C# 代码:

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
}

我得到以下 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

【讨论】:

  • 请原谅我的无知,但这是否意味着Foo.Bar 在编译时也会被强制转换?
  • @ArnoSluismans 是的,因为编译器知道它的静态类型,因此可以优化任何检查。
  • @ArnoSluismans 是的。他再次击败了我。华生先生打得好:)
  • 谢谢你们俩。 :)
【解决方案2】:

常量的转换是在编译时完成的。

为了证明这一点,您可以使用.Net Reflector 检查生成的代码。

例如这段代码:

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

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

生产:

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

或作为 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 
}

如您所见,没有发生运行时强制转换。发布或调试版本也是如此。

【讨论】:

  • 该死,你比我快一秒 :)
  • 好吧,如果有什么安慰的话,这就是我通常会发生的事情...... ;)
猜你喜欢
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 2020-07-14
相关资源
最近更新 更多