为什么 IL 设置这个值两次?
Why does the IL set this value twice?
当我输入这段代码时,我正在尝试使用 Try Roslyn:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.CSharp;
public class C {
public C()
{
x = 4;
}
public int x { get; } = 5;
}
它给了我这个代码:
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;
}
}
我不明白的是为什么它会在构造函数中对支持字段进行两次赋值:
this.<x>k__BackingField = 5;
base(); // This is not valid C#, but it represents the IL correctly.
this.<x>k__BackingField = 4;.
这是网站的错误还是 Roslyn 编译器真的这样做了(在我看来真的很愚蠢)?
我的意思是如果我这样做
public C(int x)
{
this.x = x;
}
public int x { get; } = 5;
并创建代码:
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;
}
但它不应该优化它吗?
因为你在代码中设置了两次:
public C()
{
//here
x = 4;
}
//and here
public int x { get; } = 5;
问题编辑后更新
But shouldn't it optimize that out?
它可能可以,但前提是 class 没有继承自另一个在其构造函数中使用该值的 class,它知道它是一个自动 属性 并且setter 不执行任何其他操作。
那将是很多(危险的)假设。编译器在进行这样的优化之前需要检查很多东西。
原因是您在代码中设置了两次,在 属性 声明和构造函数中。
C# 6.0 只读 属性
public int x { get; }
在赋值方面就像只读字段一样工作:您可以在构造函数中或在声明的地方设置它。
编辑
- 这个问题分为两个部分:一是当前
http://tryroslyn.azurewebsites.net/(截至2016.05.25)编译
DEBUG 模式下的代码,即使在
header 的页面。
- 其次Roslyn真的没有优化出来
只读 属性 的双重声明,所以如果你使用 VS15 和
在发布模式下编译此代码,x 将被分配两次
嗯
多次初始化只读 属性 的用法示例可以是多个构造函数的用法,其中只有一个重新定义您为 属性 设置的 "default" 值.
但是在您的情况下,优化并不是一个坏主意,可能值得将其作为功能请求提出 Roslyn github page
当我输入这段代码时,我正在尝试使用 Try Roslyn:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.CSharp;
public class C {
public C()
{
x = 4;
}
public int x { get; } = 5;
}
它给了我这个代码:
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;
}
}
我不明白的是为什么它会在构造函数中对支持字段进行两次赋值:
this.<x>k__BackingField = 5;
base(); // This is not valid C#, but it represents the IL correctly.
this.<x>k__BackingField = 4;.
这是网站的错误还是 Roslyn 编译器真的这样做了(在我看来真的很愚蠢)?
我的意思是如果我这样做
public C(int x)
{
this.x = x;
}
public int x { get; } = 5;
并创建代码:
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;
}
但它不应该优化它吗?
因为你在代码中设置了两次:
public C()
{
//here
x = 4;
}
//and here
public int x { get; } = 5;
问题编辑后更新
But shouldn't it optimize that out?
它可能可以,但前提是 class 没有继承自另一个在其构造函数中使用该值的 class,它知道它是一个自动 属性 并且setter 不执行任何其他操作。
那将是很多(危险的)假设。编译器在进行这样的优化之前需要检查很多东西。
原因是您在代码中设置了两次,在 属性 声明和构造函数中。
C# 6.0 只读 属性
public int x { get; }
在赋值方面就像只读字段一样工作:您可以在构造函数中或在声明的地方设置它。
编辑
- 这个问题分为两个部分:一是当前 http://tryroslyn.azurewebsites.net/(截至2016.05.25)编译 DEBUG 模式下的代码,即使在 header 的页面。
- 其次Roslyn真的没有优化出来 只读 属性 的双重声明,所以如果你使用 VS15 和 在发布模式下编译此代码,x 将被分配两次 嗯
多次初始化只读 属性 的用法示例可以是多个构造函数的用法,其中只有一个重新定义您为 属性 设置的 "default" 值.
但是在您的情况下,优化并不是一个坏主意,可能值得将其作为功能请求提出 Roslyn github page