Why does the IL set this value twice?

爷,独闯天下 提交于 2019-12-07 01:24:41

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!