深入理解c#的字段与属性

属性

属性的作用就是保护字段,对字段的赋值和取值进行限定 属性的本质就是两个方法,一个叫get()对取值进行限定,一个叫set()对存值进行限定,属性只是对属性的再赋值。 如果只有get是只读属性,set是只写属性。在get里面用的值是字段的值,set里面用的是value的值 所以在类里面的public 方法要访问私有字段,尽量访问属性,虽然这样可能会降低访问的效率,但是一方面会更安全地访问字段,另一方面可能是必须经过属性里的某个方法的处理才能得到这个字段的值。

代码风格

下面的例子展示了使用属性保护字段的过程,并且使用了异常处理来处理异常,并把错误信息返回而不是显示出来,这样体现了界面与业务相分离,也就是这个Person类既可以用在字符界面下,也可以用在GUI界面下,就用复用性。 这里把构造函数设置成私有的是因为,构造函数没有返回值,所以总会创建一个对象,而在Name属性的set方法里面抛出一个异常在构造函数里并不方便处理,所以把这个处理工作放在了GetAPerson这个Person类的静态方法里,这是外界创建Person类的唯一接口,也可以通过这种方法实现单例程序。 另外这个程序还是用了c#的异常处理机制,实在是方便(相比c++而言啦),Message是Exception的一个属性。

c#源代码using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace 属性与字段{class Program{static void Main(string[] args){string result;Person p = Person.GetAPerson(“”, out result);if (p==null){Console.WriteLine(result);}Console.ReadKey();}}class Person{private string _name;public string Name{get { return _name; }set{if (value == “”){throw new Exception(“名字不能为空”);}else{_name = value;}}}private Person(String name){Name = name;}外界获得一个Person对象的唯一借口;Person的名字如果创建对象成功,result存储”成功”,失败则result存储失败的原因返回创建的对象,如果对象创建失败返回NULLPerson GetAPerson(string name,out string result){Person tmp;try{tmp = new Person(name);result = “成功”;return tmp;}catch(Exception e){result =e.Message;;}}}}IL中间代码

我们我们通过reflector来分析一下这个代码的中间代码;

set方法

其中set方法如果转换为IL中间代码则变为

.method public hidebysig specialname instance void set_Name(string ‘value’) cil managed{// token: 06000002.maxstack 2//表示程序栈有两个变量.locals init (//定义一个bool类型变量,压入call stack里面[0] bool CS$4$0000)L_0000: nop // 00//什么也不做L_0001: ldarg.1 // 03//把第一个形参拿进来,就是valueL_0002: ldstr “” // 7201000070 L_0007: call bool [mscorlib]System.String::op_Equality(string, string) // 281200000AL_000c: ldc.i4.0 // 16L_000d: ceq // FE01L_000f: stloc.0 // 0AL_0010: ldloc.0 // 06L_0011: brtrue.s L_001f // 2D0CL_0013: nop // 00L_0014: ldstr “\u540d\u5b57\u4e0d\u80fd\u4e3a\u7a7a” // 7203000070L_0019: newobj instance void [mscorlib]System.Exception::.ctor(string) // 731300000AL_001e: throw // 7AL_001f: nop // 00L_0020: ldarg.0 // 02L_0021: ldarg.1 // 03L_0022: stfld string 属性与字段.Person::_name // 7D04000004L_0027: nop // 00L_0028: ret // 2A}

我们可以分析几句重要的,其它的我都做了注释

if (value == “”){throw new Exception(“名字不能为空”);}else{_name = value;}L_0001: ldarg.1 // 03//把第一个形参拿进来,,就是valueL_0002: ldstr “” // 7201000070 L_0007: call bool [mscorlib]System.String::op_Equality(string, string) // 281200000AL_000c: ldc.i4.0 // 16L_000d: ceq // FE01

ldarg.1把形参value拿过来,ldstr “”找一个字符串”“的引用拿过来,然后调用op_Equality方法比较两者一样不,ldc.i4.0表示表达式的值是这个0先压入到栈里,为了方便一会儿跳转判断用,ceq如果比较结果为真,则产生一个值为1的int变量,如果结果为假,产生一个值为0 的变量;把这个变量压入刚才的0上面。

: : : : : stfld string 属性与字段.Person::_name // 7D04000004再长的路,一步步也能走完,再短的路,不迈开双脚也无法到达。

深入理解c#的字段与属性

相关文章:

你感兴趣的文章:

标签云: