本文共 2671 字,大约阅读时间需要 8 分钟。
Noam B.:
我建了一个这样的属性。
public int Foo { get; }
毫无疑问,这是一个只读属性,当我在构造函数中无意对它赋值时,我发现居然可以改变它的值???比如下面的代码。
public MyClass(string name){ Foo = 5;}
为什么会这样?它不是只读的吗?
Yacoub Massad:
首先这是 C#6
引入的新特性,它允许我们创建只读的属性,但这里有一个问题,实践中我们常常需要给这个只读属性赋予一个非默认值,比如你这里的 Foo=5
而不是它原生的 Foo=0
,所以这是一个设计哲学问题。
如果你想在 构造函数
之外修改属性的值,这时候 ReadOnly
的限定就会让其抛出一个编译时错误了。
Rahul Nikate:
自动属性是在 C# 3.0
中被引入的,它的好处就是帮你省去了人肉 field 的繁琐,接下来你可以通过 构造函数 初始化自动属性为一个非 default 值,在 C# 6.0 中又做了进一步简化,可以直接使用 属性初始化器
对属性进行初始化操作,省去了构造函数的繁琐赋值。
在之前你可能需要这样做。
public class MyClass{ public int Foo { get; } public MyClass(int foo) { Foo = foo; }}
现在你可以使用 属性初始化器
了。
public string Foo { get; } = "SomeString";public ListGenres { get; } = new List { "Comedy", "Drama" };
其实这种问题,看 IL 代码是最清楚的。
.class public auto ansi beforefieldinit ConsoleApp3.MyClass extends [mscorlib]System.Object{ // Fields .field private initonly int32 'k__BackingField' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) // Methods .method public hidebysig specialname instance int32 get_Foo () cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Method begins at RVA 0x205c // Code size 7 (0x7) .maxstack 8 // return k__BackingField; IL_0000: ldarg.0 IL_0001: ldfld int32 ConsoleApp3.MyClass::' k__BackingField' IL_0006: ret } // end of method MyClass::get_Foo .method public hidebysig specialname rtspecialname instance void .ctor ( int32 foo ) cil managed { // Method begins at RVA 0x2064 // Code size 16 (0x10) .maxstack 8 // { IL_0000: ldarg.0 // (no C# code) IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop // Foo = foo; IL_0007: nop IL_0008: ldarg.0 IL_0009: ldarg.1 IL_000a: stfld int32 ConsoleApp3.MyClass::' k__BackingField' // } IL_000f: ret } // end of method MyClass::.ctor // Properties .property instance int32 Foo() { .get instance int32 ConsoleApp3.MyClass::get_Foo() }} // end of class ConsoleApp3.MyClass
从上面的 .field private initonly int32 '<Foo>k__BackingField'
可以看出, '<Foo>k__BackingField'
被 readonly 标记了,构造函数中只是对其原始 field 进行赋值,参考如下代码:
public class MyClass { private readonly intk__BackingField'; public MyClass(int foo) { k__BackingField' = foo; } }
转载地址:http://thydi.baihongyu.com/