2017-07-26关于set和get访问器以及value的理解
1 class TestA 2 { 3 private int? app;//这是字段 4 public int APP//这是属性 5 { 6 get//get和set类似于一种函数,原本是为访问一个类的私有成语服务的 7 { 8 int tempApp = app * 10 ?? 1; 9 return tempApp; 10 } 11 set 12 { 13 app = value; 14 } 15 } 16 17 18 private int obs; 19 public int OBS 20 { 21 get 22 { 23 return obs; 24 } 25 set//这里旨在说明无论是get还是set都可以含有逻辑处理 26 { 27 //value是传过来的值,上面也说过get和set类似于一个函数 28 //那么“demo.OBS = -10”可以理解成形参是value,这是被赋予了-10这个数字,调用“set函数” 29 if (value < 0) 30 { 31 obs = value * -1; 32 } 33 else 34 { 35 obs = value; 36 } 37 } 38 } 39 } 40 41 class Program 42 { 43 static void Main(string[] args) 44 { 45 TestA demo = new TestA(); 46 Console.WriteLine("一开始demo.APP为空,调用get后的判空逻辑后为:{0}", demo.APP); 47 demo.APP = 10; 48 Console.WriteLine("赋值语句:demo.APP = 10,调用set。。。。\n" + 49 " 此时私有成员demo.app的值为10;"); 50 Console.WriteLine("上面已经为demo.APP赋值,实际是对demo.app赋值,此时调用get后的乘10逻辑为:{0}", demo.APP); 51 52 Console.WriteLine("\n==================华丽的分割线===================\n"); 53 54 Console.WriteLine("这里调用demo.OBS的get,应该是int的默认值:{0}", demo.OBS); 55 demo.OBS = -10; 56 Console.WriteLine("赋值语句:demo.OBS = -10,调用set。。。。。。\n" + 57 " 此时私有成员demo.app的值已经是10;"); 58 Console.WriteLine("经过上面的赋值,此时的demo.OBS为:{0}", demo.OBS); 59 Console.ReadKey(); 60 } 61 }
额,本来想先写这段说明的,奈何弄了代码后无法把代码块下调,就只好写在代码后了~
C#入门的书看了不少,属性和字段的区别理解了很久感觉还是没底,我个人的理解是属性会带上访问器,而字段和C++类中的属性是一个意思。那为什么C#会字段属性不同呢?我理解的原因是,用C++举例子,属性的访问权限往往都是私有的,如果我们要访问它们,通常的做法是写对应的SetXxx()和GetXxx()函数,这会很麻烦,因此C#就有了这个语法糖(我姑且当它是语法糖了,不知道这么理解会不会有偏差)。关于这方面的只是,我觉得应该是不难,只是可能我还没有跳出C++固有的限制,所以心里老觉得怪怪的,也无心吸收书中的知识。欢迎大家指正和赐教,本文不是探讨这个问题。说说另一个这方面困扰我的一个问题,那就是set访问器中的value是什么鬼。
很多书上介绍set和get往往都是从它的历史演变介绍,典型的就是
private int _tra; public int Tra { get { return _tra; } set { tra = value; } }
然后慢慢地演变成连private字段都没有了,直接一个public并且get和set直接public int Tra{get; set;},其实这样会让新人感到一头雾水,究竟这个set和get有何用,毕竟都已经是public了,可以直接存取了,何必写get和set呢?
再者,我一直的惯性思维是重写get访问器的多,set的少(书上的例子数量也就是给人这样的感觉),所以这个value有什么用?set里究竟能不能写逻辑?
其实根本是要弄清楚get和set的作用,就拿这个_tra做例子:
get顾名思义就是得到,也就是“取”,取出这个值的意思。那么什么时候需要取出这个值?当然就是这个属性作为表达式的右值,例如a = Tra,这样a要想得到值,是不是应该取出Tra这个值然后赋给a呢。相反的set就是设置,也就是给这个属性赋值,那它当然是作为表达式的左值了,例如Tra = a。
用函数的思维去想这个事情,我们假设set和get就是函数,get函数通过名字我们第一反应应该是“得到什么”的意思,因此这个函数里是不是应该有一句return呢?而set函数是设置什么的意思,那么是不是应该传个参数让它知道设成什么呢?这就是value的作用。
其实不要脱离当初发明set和get的原因去想这件事,我之所以比喻成函数是因为以往在C++我们就是要写SetXxx()和GetXxx()函数访问私有成员,而GetXxx()函数确实肯定有返回值,SetXxx()一般都有参数,这就是get和set访问器的雏形嘛。只不过因为要好看,而且大多时候SetXxx()也就传递一个参数而已,因此C#为了简洁美和方便使用,就搞了一个value的关键字,其实相当于SetXxx()函数的参数。这个value和形参一样都共同的特点就是不会改变,不影响调用方。实际上我们也不会去修改value的值(但它是允许被修改的)
下面是开始代码的运行结果~
观看value究竟是什么鬼,我在第29行设置了一个断点进行调试,可以理解成就是一个形参。只不过函数调用的方法和真正的函数调用不太一样。
关于正式的说明,可以参考官方文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/value