这些属性声明是否相同?

时间:2017-09-11 16:16:29

标签: c# properties

这些属性声明是否相同?

public int MyProperty { get; private set;}
public int MyProperty { get; }

还有这些吗?

public int MyProperty { get; } = 123;
public int MyProperty => 123;

我在问,因为我在源代码中看到了这些内容的混合,它们在我看来是完全相同的。所以我想知道为什么他们在一个软件中混合编码风格,我需要确定我是否正确理解它。 (我的意思是两个单独的对:第1行=第2行,第3行=第4行。)如果不相同,请解释其中的差异,谢谢。

(注意这不是作业或其他东西。虽然它看起来像。; - ))

2 个答案:

答案 0 :(得分:1)

public int MyProperty { get; private set;}
public int MyProperty { get; }

不相同

public class Myclass
{
    public int MyProperty { get; private set; }
    public int MyProperty2 { get; }

    public void MyFunc()
    {
        MyProperty = 5; //This Is Legal

        MyProperty2 = 6; //This is not
    }
}

同样适用于下一对

public class Myclass
{
    public int MyProperty { get; } = 123;
    public int MyProperty2 => 123;

    public Myclass()
    {
        MyProperty = 65; //This is Legal
        MyProperty2 = 104; // This is not
    }
}

MyProperty2只是一个总是返回123的方法的快速语法。它没有底层字段。因此,每次调用它时都会评估123。 MyProperty是一个在初始化Myclass时设置为123的字段,然后get方法返回该字段。因此可以在构造函数中更改字段。

答案 1 :(得分:0)

其他人发布说他们不一样,他们是对的。我将进一步了解一些低级细节,并向您展示编译器为每个版本生成的IL(中间语言)代码。

公共吸气者,私人二传手与公众吸气者

公众吸气者和私人制定者:

public class Test1
{
    public int MyProperty { get; private set; }
}

生成:

Test1.get_MyProperty:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Test1.<MyProperty>k__BackingField
IL_0006:  ret         

Test1.set_MyProperty:
IL_0000:  ldarg.0     
IL_0001:  ldarg.1     
IL_0002:  stfld       UserQuery+Test1.<MyProperty>k__BackingField
IL_0007:  ret         

Test1..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret  

只有getter的版本:

public class Test2
{
    public int MyProperty { get; }
}

生成:

Test2.get_MyProperty:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Test2.<MyProperty>k__BackingField
IL_0006:  ret         

Test2..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret  

Public getter vs Expression-Body getter

仅限吸气:

public class Test1
{
    public int MyProperty => 123;
}

生成:

Test1.get_MyProperty:
IL_0000:  ldc.i4.s    7B 
IL_0002:  ret         

Test1..ctor:
IL_0000:  ldarg.0     
IL_0001:  call        System.Object..ctor
IL_0006:  nop         
IL_0007:  ret  

Expression-Body getter:

public class Test2
{
    public int MyProperty { get; } = 123;
}

生成:

Test2.get_MyProperty:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery+Test2.<MyProperty>k__BackingField
IL_0006:  ret         

Test2..ctor:
IL_0000:  ldarg.0     
IL_0001:  ldc.i4.s    7B 
IL_0003:  stfld       UserQuery+Test2.<MyProperty>k__BackingField
IL_0008:  ldarg.0     
IL_0009:  call        System.Object..ctor
IL_000E:  nop         
IL_000F:  ret  

正如您所看到的,其中所有4个都会在IL级别的幕后生成非常不同的结果。

根据编译器优化设置,这些设置可能不同。编译可以选择删除支持字段,如果它看不到任何使用它。对于未使用的私有设置器,它也可以执行相同的操作。

当运行时处理它们时,它们也可能以不同的方式进行jitted(just-int-time编译)。