这些属性声明是否相同?
public int MyProperty { get; private set;}
public int MyProperty { get; }
还有这些吗?
public int MyProperty { get; } = 123;
public int MyProperty => 123;
我在问,因为我在源代码中看到了这些内容的混合,它们在我看来是完全相同的。所以我想知道为什么他们在一个软件中混合编码风格,我需要确定我是否正确理解它。 (我的意思是两个单独的对:第1行=第2行,第3行=第4行。)如果不相同,请解释其中的差异,谢谢。
(注意这不是作业或其他东西。虽然它看起来像。; - ))
答案 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 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编译)。