IL级别上的表达体语法与Getter语法有什么区别?

时间:2017-10-02 09:28:02

标签: c# cil

我想了解一下IL代码。

因此,正如您所看到的,表达bodied的代码少于GetOld代码。是否在那里完成了一些优化并且意味着表达体语法更高效?

或者这无关紧要?

namespace DatabaseModules {
    public class Test {
        public IList<string> _cache = new List<string>();

        public Test() {

        }

        public IList<string> Get => _cache;

        public IList<string> GetOld {
            get { return _cache; }
        }
    }
}

使用DotPeek生成的IL代码

https://gist.github.com/anonymous/9673389a1a21d0ad8122ec97178cfd9a

2 个答案:

答案 0 :(得分:5)

没有。使用Roslyn的代码compiles to the exact same C#,所以IL也没有什么不同:

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]
namespace DatabaseModules
{
    public class Test
    {
        public IList<string> _cache = new List<string>();

        public IList<string> Get
        {
            get
            {
                return this._cache;
            }
        }

        public IList<string> GetOld
        {
            get
            {
                return this._cache;
            }
        }
    }
}

答案 1 :(得分:4)

When compiling in Release mode, both properties produce the same IL

.method public hidebysig specialname 
    instance class [mscorlib]System.Collections.Generic.IList`1<string> get_Get () cil managed 
{
    // Method begins at RVA 0x2063
    // Code size 7 (0x7)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld class [mscorlib]System.Collections.Generic.IList`1<string> DatabaseModules.Test::_cache
    IL_0006: ret
} // end of method Test::get_Get

.method public hidebysig specialname 
    instance class [mscorlib]System.Collections.Generic.IList`1<string> get_GetOld () cil managed 
{
    // Method begins at RVA 0x2063
    // Code size 7 (0x7)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld class [mscorlib]System.Collections.Generic.IList`1<string> DatabaseModules.Test::_cache
    IL_0006: ret
} // end of method Test::get_GetOld

When compiling in Debug mode, the IL is indeed different

.method public hidebysig specialname 
    instance class [mscorlib]System.Collections.Generic.IList`1<string> get_Get () cil managed 
{
    // Method begins at RVA 0x2065
    // Code size 7 (0x7)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: ldfld class [mscorlib]System.Collections.Generic.IList`1<string> DatabaseModules.Test::_cache
    IL_0006: ret
} // end of method Test::get_Get

.method public hidebysig specialname 
    instance class [mscorlib]System.Collections.Generic.IList`1<string> get_GetOld () cil managed 
{
    // Method begins at RVA 0x2070
    // Code size 12 (0xc)
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.Collections.Generic.IList`1<string>
    )

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldfld class [mscorlib]System.Collections.Generic.IList`1<string> DatabaseModules.Test::_cache
    IL_0007: stloc.0
    IL_0008: br.s IL_000a
    IL_000a: ldloc.0
    IL_000b: ret
} // end of method Test::get_GetOld

添加的说明是:

  1. nop指令,其目的是什么都不做。
  2. 一条br指令,跳转到以下指令;实际上,这没有任何作用。
  3. 一对stloc - ldloc对指令,用于存储然后从局部变量加载值,这实际上什么都不做。
  4. 因此,添加的说明不做任何事情。我相信他们中的大多数都是为了帮助调试(即nop就在那里,这样你就可以在开括号上放置一个断点;这由你的dotPeek输出中的注释表示)。其中一些可能是内部编译器如何工作的工件,并且在调试模式下不会被删除,因为没有理由这样做。

    最后,差异并不重要。并且它在发布模式下不会导致性能差异,因为在该模式下IL没有差异。