博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NET问答: 为什么仅有 getter 的属性,还可以在构造函数中赋值 ?
阅读量:4034 次
发布时间:2019-05-24

本文共 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 List
 Genres { 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 int 
k__BackingField';             public MyClass(int foo)       {           
k__BackingField' = foo;       }   }

转载地址:http://thydi.baihongyu.com/

你可能感兴趣的文章
SpringBoot通过配置devtools实现热部署
查看>>
springboot+springsecurity+jwt进行系统权限开发
查看>>
使用轻量级工具emoji-java处理emoji表情字符
查看>>
排序算法的C语言实现C代码
查看>>
c语言快排函数调用方法模板
查看>>
c语言实现多行输入输出数据
查看>>
查找算法
查看>>
C语言单链表实现
查看>>
SQL基本命令集合整理
查看>>
QT中json的生成和解析
查看>>
std::function 和 std::bind 的简单例子
查看>>
CFormView简介
查看>>
Visual Studio 2010 与 VC++ 6.0 的操作差异(一)之对话框中添加OnInitDialog()函数
查看>>
VC的MFC里面控件的ID使用ID_XXXXX和IDR_XXXXX的区别
查看>>
VC++ 获取ListControl选中行
查看>>
用VC++实现应用程序窗口的任意分割(2)
查看>>
“class”类型重定义,include(头文件)重复加载 QT /c++
查看>>
MFC框架类、文档类、视图类相互访问的方法
查看>>
<转>文档视图指针互获
查看>>
C++中头文件相互包含的几点问题
查看>>