5

Very short question but I couldn't find a solution on the web right now.

int test = 1 + 2;

Will 1 + 2 be performed during run- or compile-time?

Reason for asking: I think most people sometimes use a literal without specifying why it has been used or what it means because they do not want to waste a bit performance by running the calculation and I believe the calculate happens during compiletime and has no effect on performance:

int nbr = 31536000; //What the heck is that?

instead of

int nbr = 365 * 24 * 60 * 60; //I guess you know what nbr is supposed to be now...
Noel Widmer
  • 4,444
  • 9
  • 45
  • 69
  • 3
    Yes it is but a proper answer would reference the standard or something similar. – Martin Liversage Apr 06 '16 at 12:51
  • 5
    [7.15 Constant expressions](https://msdn.microsoft.com/en-us/library/aa691319(v=vs.71).aspx) – Alex K. Apr 06 '16 at 12:52
  • Constant expression is really just a value (evaluated at compile time). Looking at your first `nbr` definition (and after reading [this](http://stackoverflow.com/q/21501470/1997232) question) it's really very simply: don't put meaningless comment, but use comment to describe the thing. E.g. `int nbr = whatever; // whatever = 367 * 123 * 50 * 60` line suddenly make sense. – Sinatr Apr 06 '16 at 13:12
  • 4
    or `const int secondsInYear = ...` – Alex K. Apr 06 '16 at 13:15
  • @AlexK., naming good is good. – Sinatr Apr 06 '16 at 13:16
  • @Sinatr You are right but before posting I had the exact problem that I couldn't figure out the calculation of the value even by having a comment. the comment did not name the calculation but a description of the value. Still didn't figure it out. – Noel Widmer Apr 06 '16 at 13:34

3 Answers3

4

Since your examples are essentially constant expressions (i.e. they consist of only constants or constructs that evaluate as such), they will be evaluated at compile time.

A constant-expression is an expression that can be fully evaluated at compile-time.

The type of a constantexpression can be one of the following: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, any enumeration type, or the null type.

The following constructs are permitted in constant expressions:

  • Literals (including the null literal).
  • References to const members of class and struct types.
  • References to members of enumeration types.
  • Parenthesized sub-expressions, which are themselves constant expressions.
  • Cast expressions, provided the target type is one of the types listed above.
  • The predefined +, , !, and ~ unary operators.
  • The predefined +, , *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
  • The ?: conditional operator.
Rion Williams
  • 74,820
  • 37
  • 200
  • 327
3

The expression 1 + 2 in int test = 1 + 2 is considered to be a "constant-expression" according to the C# spec:

7.19 Constant expressions

A constant-expression is an expression that can be fully evaluated at compile-time.

In other words: when an expression can be fully evaluated at compile-time, it is considered to be a "constant expression", and those will be evaluated at compile-time.

Kind of a catch-22 when you want to discover the meaning of a constant expression and compile-time evaluation.

To apply the relevant parts of the spec to your example:

A constant expression must be [...] a value with one of the following types: [...] int [...].

Only the following constructs are permitted in constant expressions:

  • Literals (including the null literal).

  • [...]

  • The predefined +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.

[...]

Whenever an expression fulfills the requirements listed above, the expression is evaluated at compile-time.

The last line would be clearer if it would read:

Whenever an expression fulfills the requirements listed above, the expression is [considered to be a constant expression and will be] evaluated at compile-time.

When an expression contradicts any of the listed rules (including things such as using a non-const member invocation or a method call), it will not be considered a constant expression and thus be evaluated at runtime.

Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • It's not really a catch-22. "When an expression can be evaluated at compile time, it is considered a constant expression. Constant expressions are evaluated at compile time" is equivalently expressed as "When an expression can be evaluated at compile time, it will be". – Richard Irons Apr 06 '16 at 14:29
  • @Richard yeah it was more in reaction to this question: _"Which expressions are evaluated at compile-time?"_, to which the answer is _"Constant expressions!"_. From that the question follows: _"But what are constant expressions? "_, which is answered by _"Expressions that can be evaluated at compile-time!"_, ad infinitum. – CodeCaster Apr 06 '16 at 15:01
  • 1
    Ah, yes, I see. I guess really the answer to the first question should be "everything that can be!". – Richard Irons Apr 06 '16 at 16:16
1

Well just tested it with IlSpy and for code :

private static void Main(string[] args)
{
    int value = 365 * 24 * 60 * 60;
    Console.WriteLine(value);
}

Compiled MSIL code is :

.....

IL_0000: nop
IL_0001: ldc.i4 31536000       // its calculated already
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call void [mscorlib]System.Console::WriteLine(int32)
IL_000d: nop
IL_000e: ret
} // end of method Program::Main

So it does calculate static expression in compile time to improve performance however if we change our code to :

double nbr = Math.Sqrt(365 * 24 * 60 * 60);

Console.WriteLine(nbr);

This time the final result will be populated on run-time because compiler doesn't know value that will be returned by Math.Sqrt() on compile time.

MsIL code :

IL_0000: nop
IL_0001: ldc.r8 31536000
IL_000a: call float64 [mscorlib]System.Math::Sqrt(float64)
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: call void [mscorlib]System.Console::WriteLine(float64)
IL_0016: nop
IL_0017: ret
} // end of method Program::Main
Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • Sure, Math.Sqrt() would have to return a constant expression for this to work. But I am pretty sure we cannot achieve that in C#. – Noel Widmer Apr 06 '16 at 13:35
  • Well the point is that if we need to calculate something that has constant value we can do it once and save this value in msil code so that there will be no redundant calculations at run-time. But it works only with simple constant expressions. – Fabjan Apr 06 '16 at 13:41