C#中字段、属性与方法、事件的关系
打开类设计器,可以看到一个类的详细信息中有:字段、属性、方法、事件四个项。我大体知道,方法是对属性进行操作的,事件是会使用一系列方法,并改变一系列属性。不过字段和属性有什...
打开类设计器,可以看到一个类的详细信息中有:字段、属性、方法、事件四个项。
我大体知道,方法是对属性进行操作的,事件是会使用一系列方法,并改变一系列属性。
不过字段和属性有什么关系呢?
比如我随便写一个整型线性表类:
public class statelist
{
//构造函数
public statelist()
{
//初始化
head = null;
tail = null;
current = null;
}
private int head; //头指针
private int tail; //尾指针
private int current; //当前指针
}
}
在类设计器中查看,为什么head、tail、current都是字段?它们不是属性吗? 展开
我大体知道,方法是对属性进行操作的,事件是会使用一系列方法,并改变一系列属性。
不过字段和属性有什么关系呢?
比如我随便写一个整型线性表类:
public class statelist
{
//构造函数
public statelist()
{
//初始化
head = null;
tail = null;
current = null;
}
private int head; //头指针
private int tail; //尾指针
private int current; //当前指针
}
}
在类设计器中查看,为什么head、tail、current都是字段?它们不是属性吗? 展开
3个回答
展开全部
class Student
2
3{
4
5 public string name;//这就是字段
6
7}
8
9class Student
10
11{
12
13 private string name;
14
15 public string Name //这就是属性
16
17 {
18
19 get
20
21 {
22
23 return name;
24
25 }
26
27 set
28
29 {
30
31 name = value;
32
33 }
34
35 }
36
37}
在<<Effective C#>>书中有这样一条原则,尽量用属性去取代字段。这就进入了学习语言的第二阶段,Why?对啊,为什么呢?用属性代替字段有什么好处呢?
我认为原因有三:
第一,属性比字段更面向对象,具体就体现在封装性上。什么是封装性呢?前两天我给班级哪位同学讲题的时候我问到了他这个问题。他告诉我,把字段给声明为private就是封装了。在这里,我指出一下,也许大家都会有这样的想法,其实封装有很多,他所指的只是属性的封装,另外,还包括类的封装,模块的封装,组件的封装等等。在这里不做详细讨论,如果想更深入地了解封装,请更好地理解什么是面向对象,这很重要!但是在这里,有一点很正确,就是说属性确实比字段更能够体现封装性。我相信对我以上的例子,很多人都说,在第一个例子中,字段name是可读可写的。在第二个例子中,属性Name同样是提供了对name的可读可写,我用什么有什么区别呢?请大家继续向下看。
第二,字段不能进行控制,而属性可以解决这样的问题。说最常用的例子,我可以设置对属性的赋值或者访问控制。
举个例子,我相信每个人都不希望自己的名字叫做SB(有特殊需求者除外)。仍然沿用上面的代码,我在主程序中这样写Student s=new Student();s.name=”SB”;完了,这个学生s可真够倒霉的,被起了一个这样的名字。但是用属性就可以很好地防止这样的情况,代码如下:
Code
1 class Student
2
3 {
4
5 private string name;
6
7 public string Name
8
9 {
10
11 get
12
13 {
14
15 return name;
16
17 }
18
19 set
20
21 {
22
23 if (value != "SB")
24
25 {
26
27 name = value;
28
29 }
30
31 }
32
33 }
34
35 }
36
37
这时,学生就可以骄傲地说,他妈的,看以后谁还敢给我起名叫SB.
第三,因为我上课没有听过课,但是我感觉按现在的进度应该没讲到那个位置。就是说数据的绑定的问题。在这里,我就不再深谈。大家只要记得,属性支持绑定,而字段不支持绑定就可以了。
有些人可能这时候有这样的想法,我现在不需要绑定,也不需要对他进行控制。既然我本来也要把name属性声明为可读可写的,我就把它声明为字段算了。代码如下:
class Student
{
public string Name;
}
曾经我也有过这样的想法,但是有些人这个时候对这个很不屑一顾,但是他的理由却肯定是,如果我有一天,这个Name我不想让别人给我赋值了,也就是说只具有只读属性了,怎么办?那我告诉你,你想的还是最浅显的,这个很容易解决。因为在这里,我已经把Name字段给大写了,所以我以后只需要把Name字段改成小写,然后再写一个属性就哦了!代码如下:
class Student
{
private string name;
public string Name
{
get
{
return name;
}
}
}
我也只是改了一个地方,客户端调用处我一样没有进行修改。你还能说出什么么?
但是,现在,我想告诉大家的是,这样的确是不好的,但是理由不是上面说的那样。这里涉及到了一个概念,叫“二进制组件”。相信这对于很多人来说是个比较新的概念。什么是二进制组件呢?我个人的理解是这样的,每个人都应该知道,计算机并不认识任何代码,他能识别的只有0和1,这是二进制。那组件呢?组件具有一组功能的类的集合,可以用来单独发布以完成某个功能。其实二进制组件就是这样的集合编译后执行后产生的东东。大家也许还有点庸,不用着急,这个不用理解。我们清楚.NET的执行过程是首先把C#代码翻译成IL语言,然后IL语言再编译成二进制代码。那么我们就来看看IL,放心,不用怕,我会给出IL的具体注释。(我这里现在不大方便打开VS,所以IL是自己写的,如果哪里有错误,还希望见谅)
首先是字段的IL(包括字段的声明以及字段的取值赋值):
.field public string name //这里是IL中字段的声明
ldloc.0 //load location 就是说读取name所在的地址
ldfld string Student:Name //load field 就是说读取name字段的值
stloc.1 //将其压栈至位置1
ldloc.0 // load location 就是说读取name所在的地址
ldstr “SB” //读取字符串”SB”
stfld string Student:name //将”SB”赋给字段name
然后是属性的取值赋值(我IL造诣实在不深,只写个方法体吧,具体代码就不写了,太折磨人了):
.property instance string Name()
{
.get instance string Student:get_name(); //get操作
.set instance void Student:set_name(string) //set操作
}
大家看不懂不要紧,但是大家应该可以很清楚地看到,两段代码是截然不同的。于是就出现了一句很经典的话,叫在数据成员和属性之间转换会破坏二进制的兼容性。(印象中是这样的,不敢保证,但是大概就是这个意思)。
上面的属性为何会编译成的代码,在下面的属性和方法篇中,我会详细讲解。
希望看完以上的文章,大家也许半懂不懂,这是需要细细地一遍遍去阅读的。但大家一定要记住一点,除非极特殊(至少我现在还没有碰到过),都不要把字段声明为public。但是就认定把字段声明为private是不对的。在很多应用中,都会把字段声明为protected.以后随着大家项目经验的丰富,我相信大家会逐渐体验到。
2
3{
4
5 public string name;//这就是字段
6
7}
8
9class Student
10
11{
12
13 private string name;
14
15 public string Name //这就是属性
16
17 {
18
19 get
20
21 {
22
23 return name;
24
25 }
26
27 set
28
29 {
30
31 name = value;
32
33 }
34
35 }
36
37}
在<<Effective C#>>书中有这样一条原则,尽量用属性去取代字段。这就进入了学习语言的第二阶段,Why?对啊,为什么呢?用属性代替字段有什么好处呢?
我认为原因有三:
第一,属性比字段更面向对象,具体就体现在封装性上。什么是封装性呢?前两天我给班级哪位同学讲题的时候我问到了他这个问题。他告诉我,把字段给声明为private就是封装了。在这里,我指出一下,也许大家都会有这样的想法,其实封装有很多,他所指的只是属性的封装,另外,还包括类的封装,模块的封装,组件的封装等等。在这里不做详细讨论,如果想更深入地了解封装,请更好地理解什么是面向对象,这很重要!但是在这里,有一点很正确,就是说属性确实比字段更能够体现封装性。我相信对我以上的例子,很多人都说,在第一个例子中,字段name是可读可写的。在第二个例子中,属性Name同样是提供了对name的可读可写,我用什么有什么区别呢?请大家继续向下看。
第二,字段不能进行控制,而属性可以解决这样的问题。说最常用的例子,我可以设置对属性的赋值或者访问控制。
举个例子,我相信每个人都不希望自己的名字叫做SB(有特殊需求者除外)。仍然沿用上面的代码,我在主程序中这样写Student s=new Student();s.name=”SB”;完了,这个学生s可真够倒霉的,被起了一个这样的名字。但是用属性就可以很好地防止这样的情况,代码如下:
Code
1 class Student
2
3 {
4
5 private string name;
6
7 public string Name
8
9 {
10
11 get
12
13 {
14
15 return name;
16
17 }
18
19 set
20
21 {
22
23 if (value != "SB")
24
25 {
26
27 name = value;
28
29 }
30
31 }
32
33 }
34
35 }
36
37
这时,学生就可以骄傲地说,他妈的,看以后谁还敢给我起名叫SB.
第三,因为我上课没有听过课,但是我感觉按现在的进度应该没讲到那个位置。就是说数据的绑定的问题。在这里,我就不再深谈。大家只要记得,属性支持绑定,而字段不支持绑定就可以了。
有些人可能这时候有这样的想法,我现在不需要绑定,也不需要对他进行控制。既然我本来也要把name属性声明为可读可写的,我就把它声明为字段算了。代码如下:
class Student
{
public string Name;
}
曾经我也有过这样的想法,但是有些人这个时候对这个很不屑一顾,但是他的理由却肯定是,如果我有一天,这个Name我不想让别人给我赋值了,也就是说只具有只读属性了,怎么办?那我告诉你,你想的还是最浅显的,这个很容易解决。因为在这里,我已经把Name字段给大写了,所以我以后只需要把Name字段改成小写,然后再写一个属性就哦了!代码如下:
class Student
{
private string name;
public string Name
{
get
{
return name;
}
}
}
我也只是改了一个地方,客户端调用处我一样没有进行修改。你还能说出什么么?
但是,现在,我想告诉大家的是,这样的确是不好的,但是理由不是上面说的那样。这里涉及到了一个概念,叫“二进制组件”。相信这对于很多人来说是个比较新的概念。什么是二进制组件呢?我个人的理解是这样的,每个人都应该知道,计算机并不认识任何代码,他能识别的只有0和1,这是二进制。那组件呢?组件具有一组功能的类的集合,可以用来单独发布以完成某个功能。其实二进制组件就是这样的集合编译后执行后产生的东东。大家也许还有点庸,不用着急,这个不用理解。我们清楚.NET的执行过程是首先把C#代码翻译成IL语言,然后IL语言再编译成二进制代码。那么我们就来看看IL,放心,不用怕,我会给出IL的具体注释。(我这里现在不大方便打开VS,所以IL是自己写的,如果哪里有错误,还希望见谅)
首先是字段的IL(包括字段的声明以及字段的取值赋值):
.field public string name //这里是IL中字段的声明
ldloc.0 //load location 就是说读取name所在的地址
ldfld string Student:Name //load field 就是说读取name字段的值
stloc.1 //将其压栈至位置1
ldloc.0 // load location 就是说读取name所在的地址
ldstr “SB” //读取字符串”SB”
stfld string Student:name //将”SB”赋给字段name
然后是属性的取值赋值(我IL造诣实在不深,只写个方法体吧,具体代码就不写了,太折磨人了):
.property instance string Name()
{
.get instance string Student:get_name(); //get操作
.set instance void Student:set_name(string) //set操作
}
大家看不懂不要紧,但是大家应该可以很清楚地看到,两段代码是截然不同的。于是就出现了一句很经典的话,叫在数据成员和属性之间转换会破坏二进制的兼容性。(印象中是这样的,不敢保证,但是大概就是这个意思)。
上面的属性为何会编译成的代码,在下面的属性和方法篇中,我会详细讲解。
希望看完以上的文章,大家也许半懂不懂,这是需要细细地一遍遍去阅读的。但大家一定要记住一点,除非极特殊(至少我现在还没有碰到过),都不要把字段声明为public。但是就认定把字段声明为private是不对的。在很多应用中,都会把字段声明为protected.以后随着大家项目经验的丰富,我相信大家会逐渐体验到。
参考资料: http://www.cnblogs.com/xinyuperfect/archive/2008/10/28/1294664.html
展开全部
public class userInfo
{
//字段
private string name; //其它类不能访问
public int age; //其它类可访问,但既可赋值,也可取值。
//属性
public string Name //其它类可访问,但只能赋值,不能取值。
{
//注释了get就只能给Name赋值,而不能取值。反之依然
//get{return name;}
set
{
//TODO:可以调用方法等其它操作。 这里就是一个方法,方法名为set,参数为value;
name=value;
}
}
}
{
//字段
private string name; //其它类不能访问
public int age; //其它类可访问,但既可赋值,也可取值。
//属性
public string Name //其它类可访问,但只能赋值,不能取值。
{
//注释了get就只能给Name赋值,而不能取值。反之依然
//get{return name;}
set
{
//TODO:可以调用方法等其它操作。 这里就是一个方法,方法名为set,参数为value;
name=value;
}
}
}
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
废话 你这样写不是字段是什么啊`!
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询