问题
I was trying around a bit with Try Roslyn when I entered this piece of code:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.CSharp;
public class C {
public C()
{
x = 4;
}
public int x { get; } = 5;
}
And it gave me back this code:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
[assembly: AssemblyVersion("0.0.0.0")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[module: UnverifiableCode]
public class C
{
[DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated]
private readonly int <x>k__BackingField;
public int x
{
[CompilerGenerated]
get
{
return this.<x>k__BackingField;
}
}
public C()
{
this.<x>k__BackingField = 5;
base(); // This is not valid C#, but it represents the IL correctly.
this.<x>k__BackingField = 4;
}
}
What I don't get is why it would do the assignment of the backing field twice inside of the constructor:
this.<x>k__BackingField = 5;
base(); // This is not valid C#, but it represents the IL correctly.
this.<x>k__BackingField = 4;.
Is this an error of the website or does the Roslyn compiler actually do this (would be really dumb imo)?
What I mean is that if I do
public C(int x)
{
this.x = x;
}
public int x { get; } = 5;
And have that code created:
public C(int x)
{
this.<x>k__BackingField = 5;
base(); // This is not valid C#, but it represents the IL correctly.
this.<x>k__BackingField = x;
}
But shouldn't it optimize that out?
回答1:
The reason is that you are setting it twice in your code, both in the property declaration and in the constructor.
The C# 6.0 readonly property
public int x { get; }
Works just like a readonly field regarding value assignment: you can set it in either the constructor or at the place of the declaration.
EDIT
- There are two parts of this issue: First, the current http://tryroslyn.azurewebsites.net/ (as of 2016.05.25) compile the code in DEBUG mode, even if the Release option is chosen at the header of the page.
- Second the Roslyn really does not optimize out the double declaration of the readonly property, so if you use VS15 and compile this code in release mode, the x will be assigned twice as well
An example for the usage of initializing the readonly property for multiple time can be the usage of multiple constructors, where only one redefines the "default" value you set for the property.
However in your case, optimization would not be a bad idea, it might be worthwhile to raise this as a feature request on the Roslyn github page
回答2:
Because you set it twice in your code:
public C()
{
//here
x = 4;
}
//and here
public int x { get; } = 5;
Update after edit of question
But shouldn't it optimize that out?
It probably could, but only if that class doesn't inherit from another class that uses that value in its constructor, it knows that it's an auto-property and the setter doesn't do anything else.
That would be a lot of (dangerous) assumptions. The compiler needs to check a lot of things before making an optimization like that.
来源:https://stackoverflow.com/questions/37436633/why-does-the-il-set-this-value-twice