Understanding Compiler Optimizations
I'm trying to understand what the compiler is doing to very simple piece of code:
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}
After compiling in Debug
configuration, then decompiling I see this:
if (group.ImageHeight <= 1 || group.ImageWidth <= 1);
Decompiling a Release
configuration results in
if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}
More complete (original) code:
public class Group
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}
//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}
Here are my guesses and observations so far:
- When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.
- I believe that it's important that
group
type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition forgroup
. - In the
Release
config the possible side effects appear to be the same as my code:ImageHeight
is evaluated and if meets the> 1
condition will evaluateImageWidth
(although through assignment rather than comparison)
Now, for my specific questions:
- Why does the
Release
config use an assignment (int imageWidth = group.ImageWidth
) rather than my original comparison? Is it faster to run an assignment? - Why does the
Debug
configuration completely change the possibility of side effects? In this configuration bothImageHeight
andImageWidth
will always be evaluated.
c# .net compiler-construction compiler-optimization
add a comment |
I'm trying to understand what the compiler is doing to very simple piece of code:
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}
After compiling in Debug
configuration, then decompiling I see this:
if (group.ImageHeight <= 1 || group.ImageWidth <= 1);
Decompiling a Release
configuration results in
if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}
More complete (original) code:
public class Group
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}
//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}
Here are my guesses and observations so far:
- When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.
- I believe that it's important that
group
type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition forgroup
. - In the
Release
config the possible side effects appear to be the same as my code:ImageHeight
is evaluated and if meets the> 1
condition will evaluateImageWidth
(although through assignment rather than comparison)
Now, for my specific questions:
- Why does the
Release
config use an assignment (int imageWidth = group.ImageWidth
) rather than my original comparison? Is it faster to run an assignment? - Why does the
Debug
configuration completely change the possibility of side effects? In this configuration bothImageHeight
andImageWidth
will always be evaluated.
c# .net compiler-construction compiler-optimization
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
1
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16
add a comment |
I'm trying to understand what the compiler is doing to very simple piece of code:
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}
After compiling in Debug
configuration, then decompiling I see this:
if (group.ImageHeight <= 1 || group.ImageWidth <= 1);
Decompiling a Release
configuration results in
if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}
More complete (original) code:
public class Group
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}
//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}
Here are my guesses and observations so far:
- When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.
- I believe that it's important that
group
type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition forgroup
. - In the
Release
config the possible side effects appear to be the same as my code:ImageHeight
is evaluated and if meets the> 1
condition will evaluateImageWidth
(although through assignment rather than comparison)
Now, for my specific questions:
- Why does the
Release
config use an assignment (int imageWidth = group.ImageWidth
) rather than my original comparison? Is it faster to run an assignment? - Why does the
Debug
configuration completely change the possibility of side effects? In this configuration bothImageHeight
andImageWidth
will always be evaluated.
c# .net compiler-construction compiler-optimization
I'm trying to understand what the compiler is doing to very simple piece of code:
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}
After compiling in Debug
configuration, then decompiling I see this:
if (group.ImageHeight <= 1 || group.ImageWidth <= 1);
Decompiling a Release
configuration results in
if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}
More complete (original) code:
public class Group
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}
//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}
Here are my guesses and observations so far:
- When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.
- I believe that it's important that
group
type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition forgroup
. - In the
Release
config the possible side effects appear to be the same as my code:ImageHeight
is evaluated and if meets the> 1
condition will evaluateImageWidth
(although through assignment rather than comparison)
Now, for my specific questions:
- Why does the
Release
config use an assignment (int imageWidth = group.ImageWidth
) rather than my original comparison? Is it faster to run an assignment? - Why does the
Debug
configuration completely change the possibility of side effects? In this configuration bothImageHeight
andImageWidth
will always be evaluated.
c# .net compiler-construction compiler-optimization
c# .net compiler-construction compiler-optimization
edited Jan 18 at 18:30
Amy
21.7k1874131
21.7k1874131
asked Jan 18 at 17:28
MikeHMikeH
3,268927
3,268927
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
1
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16
add a comment |
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
1
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
1
1
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16
add a comment |
1 Answer
1
active
oldest
votes
For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54258811%2funderstanding-compiler-optimizations%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
add a comment |
For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
add a comment |
For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret
For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.
if (group.ImageHeight > 1)
IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012
int imageWidth = group.ImageWidth;
IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop
IL_0012: ret
For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015
IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016
IL_0015: ldc.i4.0
IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c
IL_001a: nop
IL_001b: nop
IL_001c: ret
answered Jan 18 at 18:27
Ondřej KubíčekOndřej Kubíček
1013
1013
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
add a comment |
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.
– MikeH
Jan 18 at 18:45
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54258811%2funderstanding-compiler-optimizations%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.
– Sql Surfer
Jan 18 at 18:00
1
Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.
– Damien_The_Unbeliever
Jan 18 at 18:39
@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)
– MikeH
Jan 18 at 18:43
Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines
– Damien_The_Unbeliever
Jan 18 at 19:16