中易网

请教c#/vb.net高手{ get; set; }属性的写法问题。

答案:5  悬赏:30  
解决时间 2021-01-18 09:58
请教c#/vb.net高手{ get; set; }属性的写法问题。
最佳答案
这种写法在.net 2.0后才出现的,目的是为了减轻程序员的工作量,编译器会自动为你补充完整,如:
public string name{get;set;}
编译器自动生成(可能会更负责更完善):

private string name;
public string Name
{
get { return name; }
set { name= value; }
}

这种写法在一般时候很好,但是有一种情况你不得不放弃这种写法,那就是你要在里面进行校验的时候,比如set中有运算或者校验之类的,get中有转换等等,这种情况下,你就必须老老实实的写个完整的才可以。追问假如成员变量有a,b两个,属性名是Name,编译器如何知道我想对应a,还是b?追答明白你的困惑在哪里了,使用这种简洁的写法时,你不用去单独声明a和b,只需要写:
public string a{get;set;}
public string b{get;set;}

编译器会主动为你生成:
private string a;
public string A
{
get { return a; }
set { name= a; }
}

private string b;
public string B
{
get { return b; }
set { name= b; }
}

不知道你能明白?
给你补充一下:
你可能在想,你声明了两个变量a,b,然后又写了一个public string Name{get;set;}
你困惑的是这个Name到底指的是a还是b,是吧?
如果你这么写的话,你这个类中就存在三个变量了,a,b和name,你能明白了吗?追问你的意思是大小写必须对应?如果不对应编译器就不认识了,上面的如果手写的效果是一样的么?追答和大小写没关系,给你简单写一个小例子吧,你再不明白,就直接百度HI我吧。
class Test{
public string firstName;//这就好比你说的a
public string lastName;//这就好比你说的b
public string Color{//这是一个简单的属性
get;set;

}

}

这个类编译完后:
class Test{
public string firstName;//这就好比你说的a
public string lastName;//这就好比你说的b

public string color;

public string Color{//这是一个简单的属性
get{return this.color;};
set{this.color = value};

}

}
看懂了吗?color就是单独一个属性color,跟firstName和lastName一点关系都没有。追问那假如声明属性之前,我自己声明了一个名叫color的成员变量(与属性Color绝无关系),那编译器又会生成对应的成员变量名叫什么?追答首先说,没有这么写的,要注意你写的类,可能会在vb等其他语言中调用,那些语言是不区分大小写的;

然后,如果你真的这么写了,那么你访问的时候,color就是color,跟Color一点关系都没有,因为你等于定义了两个变量,所以他们都是独立存在的,但是Color这个属性,编译器还是会自动生成一个变量,存储在类的内存中,并且有两个函数,一个set 一个get,分别去操作自动生成的这个变量(有可能是x,y,z,a,b,c...到底生成的是个啥,可能是个k__BackingField,我们不用去知道),你需要知道的就是:你定义了一个Color属性,并且允许get和set,就可以了,明白了吗追问你的意思我基本了解了,现在再来反思网上看到的一些高人的简洁的写法,大概只是想增加这么个属性,以便利用属性相对应成员变量的更多的性质吧,并不是想与哪个成员变量对应。以前我还以为必须和成员变量对应。。。追答现在设计模式很多采用实体类的,如果对数据库中每个字段去写,很累,因为也没有特殊的处理,所以一般都这么简单的写,确实少写了很多的代码

不过你明白了就行啊
大家都挺辛苦,也很认真的和你讲解,不管你采纳谁,记得和大家说声“:谢谢。
或许下次你还会回来请教大家。
全部回答
这个是自动属性,简化属性写法,编译器会为你补足具体的代码。
public string Name{get;set;}
等价于
private string name;
public string Name{get{return name;}set{name=value;}}追问编译器怎么知道属性对应哪个成员变量?追答自动属性是C#3.0的新特性,你不需要知道对应哪个成员变量,因为你调用时只是使用Name这个属性。追问假如成员变量有a,b两个,属性名是Name,编译器如何知道我想对应a,还是b?追答a和b跟Name没半毛钱关系。你为什么非要那个类成员?
不管在外部类调用,还是在当前类中调用,都只调用这个属性就行了,根本和它对应的什么类成员没什么关系。
如外部类调用:xxx.Name="Jim";
在类内部调用也只要用:Name="Jim"
这里都不需要什么对应的成员变量。追问不是我非要用,而是很多高人写的程序都是那样,只有个get;set;让人迷惑。追答这么说吧,具体跟哪个类变量对应这个只能问编译器,它可能随机分配一个变量名,而这个变量具体叫什么这个你不用知道的,你只需要用Name这个属性就行了,会通过它访问到这个类成员变量。
你的想法是正确的,但是没人说一个get,一个set就是完整的写法了啊。。。它被省略了而已,举个例子
class xxxx
{
private int a;
public int _a
{
get { return a; }
set { a = value; }
}
}
明白?追问我的意思是看到过大量的,而且明显是老手写的代码,只有get;set;的,如何解释?追答比如我上面写的函数,写get和set就够了,它的值就已经置好了。写那么多又不会加工资。。。这个老手还是新手压根一点关系都没有。再举个例子,你应该知道默认构造函数这个东西,难不成我新增一个类都需要去写一个默认的构造函数么,又不是必要的东西。而且,析构函数你压根都没写,那你类调用完了之后难不成还不能退出了啊追问怎么扯到构造函数上去了,那光说属性的话,不用return 和 value,它内部是如何与成员变量对应起来的?举实际的代码例子吧。追答你没理解我的意思,不是说不用,而是说被省略了。追问请用代码举例,说明这种省略写法不是多余的。追答我可不可以理解为你的问题是为什么构造函数里面要写成这个模式
private string name;
public string Name{get{return name;}set{name=value;}},
为什么不直接写一个private string name 就够了?追问摆脱,我在问属性,和构造函数有何关系?你如果写一个完整的程序,传附件证明,我就采纳你。追答usingSystem;
classMyClass
{
private int integer;
public int Integer
{
get{return integer;}
set{integer=value;}
}
}
classTest
{
publicstaticvoidMain()
{
MyClass MyObject=newMyClass();
Console.Write(MyObject.Integer);
MyObject.Integer++;
Console.Write(MyObject.Integer);
}
}追问这么说你还是用了return和value,没有证明不用也可以。追答usingSystem;
classMyClass
{
public int integer;
}
classTest
{
publicstaticvoidMain()
{
MyClass MyObject=newMyClass();
Console.Write(MyObject.Integer);
MyObject.Integer++;
Console.Write(MyObject.Integer);
}
}追问你这没有用属性。追答看了其他回答终于理解你的问题。其实在学的时候也不明白为什么先定义一个name,再来个属性Name。据老师说是这就是微软的命名规则,这样写就能对应上了,具体没有深究。我是理解为一个固定写法。期待高人回答。
class Class1
{
    public string Arg{get;set;}
}
这种写法是简写形式,当用编译器编译时,编译器会自动补足所需代码:
class Class1
{
    private string _Arg;//这个变量是由编译器随机生成的,不一定是_Arg这个名字
    public string Arg{get{return _Arg;}set{_Arg=value;}}
}追问你的意思是必须由编译器自动产生才行?而不是编译器根据首字母大小写的唯一差别来判定?追答
不是要编译器自动产生才行,是当你使用简写时,编译器就会自动补足。
一般情况下,我们创建属性会这样写:
class Class1
{
    private int arg;
    public int Arg{get{return arg;}set{arg=value;}}
}
但有些人为了省工作量,不对属性作访问修饰时,就可以使用简写形式class Class1
{
    public int Arg{get;set;}
}
当我们需要对属性作访问修饰时,就要写全面的代码了,譬如上面例子,假如Arg为非负整数,我们就需要在set访问器或get访问器中进行过滤,保证Arg为非负整数class Class1
{
    private int arg;
    public int Arg
    {
        get{return arg;}
        set{arg = value >= 0 ? value : 0;}
    }
}
此时不能使用简写形式追问你说的编译器自动补足,是指编译的时候还是编辑器里面就不足了?如果是编辑器,刚刚我试了一下,怎么没有呢?如果是编译器的话,那这种写法有实际意义么?追答
是在编译成中间代码时才会发生补足,譬如你要编译一个cs文件为dll时,才会补足,你要想看到它补足后的代码,可以通过反编译工具查看此dll,但知道它对应那个成员变量并没有什么意义,因为这个成员变量是一个私有变量,外部无法访问。


至于简写有什么意义,前面都说了,是为了减轻工作量,C#里面有很多简写的方法,譬如刚才例子用到的三元运算符:
arg = value >= 0 ? value : 0;
相当于:if(value >= 0)
{
    arg = value;
}
else
{
    arg = 0;
}
但用了三元运算符就省下了很多代码
先回答你的疑问
假如成员变量有a,b两个,属性名是Name,编译器如何知道我想对应a,还是b?
编译器是不可能把Name对应到a或者b这两个的任何一个
如果你想让编译器对应a
那么你的代码应该是
Public string A{get;set;}
b是一样的道理
至于为什么要写成{get;set;} 是因为这样写开发速度显然要比加上return要高
而且这样写与加上return那样写达到的效果是一样的
如果你对达到的效果一样有疑问的话你可以用反编译器查看这两种生成的代码
使用第一种
private string name;
public string Name
{
get { return name; }
set { name= value; }
}
与使用第二种
public string Name{get;set ;}
最后编译器都生成一种代码就是:
private string _name;
public string Name
{
get { return _name; }
set { _name= value; }
}
如有疑问请追问追问那么问题的关键就是,对于这种只有首字母大小写不同的成员变量与属性的对应,微软msdn有没有正式的说明?追答MSDN上的介绍是说
在 C# 3.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁。客户端代码还可通过这些属性创建对象。如下面的示例所示声明属性时,编译器将创建一个私有的匿名支持字段,该字段只能通过属性的 get 和 set 访问器进行访问。
自动属性就是{get;set;}这样的简洁写法
上面说到 编译器将创建一个私有的匿名支持字段 (可以理解为编译器创建的这个私有字段一定是你声明的字段的小写并且前面加下划线)
例如Name 对应的应该为_name
如果你不相信的话 你可以使用反编译器自己去看追问哦,那你的意思就是用下划线的唯一区别来验证了,那如果是是手工写的也能达到这种对应效果吗?追答下划线是编译器编译时自动添加的
开发人员也可以使用下划线
例如
private string _name;
public string Name
{
get { return _name; }
set { _name= value; }
}
至于编译器是如何将_name于Name对应的这个不可知道(你只有去问开发VS的人了)
不过你可以不这样对应
例如
private string _a;
public string Name
{
get { return _a; }
set { _a= value; }
}
这样也可以 系统不会报错
但是这样存在的问题很明显
就是让_a去对应Name 这样不大合逻辑 最好是让_name 对应Name追问你的意思就是说凡是属性是get;set;这样最简略的写法的话,对应一定是由编译器自动完成的,而且程序员无法知此属性是否与自定义的某个成员变量想对应,不管成员变量的变量名的写法?追答请看代码
public class Class1
{
private string _a;
private string _name;
private string name;
public string Name { get; set; }
}
编译后的代码为
public class Class1
{
// Fields
private string _a;
private string _name;
private string name;
// Methods
public Class1();
// Properties
public string Name {
get;
set; }
}
这里的public string Name { get; set; }对应的代码为
public string Name {
returnthis.k__BackingField;//get
this.k__BackingField=value;//set
}
从这里可以看出你所说的
凡是属性是get;set;这样最简略的写法的话,对应一定是由编译器自动完成的,这句话是正确的
后一句话应该改为
程序员可以断定此属性不与自定义的某个成员变量对应,不管成员变量的变量名的写法追问谢谢了你写得很详细,不过回答稍慢,所以采纳别人了。追答没关系 我是去重下了一个Reflector 然后谢了一个类 去反编译看个究竟
才发现了真正的原理 同时也纠正了我的一个错误追问private int get_X;
private int set_X;
public int X { get; set; }
后来我试了一下,这样编译不通过,编(辑)译器在背后生成了什么更清楚了。追答恩
我要举报
如以上问答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
玉品轩玉器行地址在哪,我要去那里办事
豹子号100元值多少钱
为什么大家都说京东没有希望超过阿里巴巴呢?
‘在乡下,小路上,石桥边,有撑起伞慢慢走着的
逝者后人将骨灰埋到我家耕地里该怎么办
我们俩到底合不合适?我24她27我属猴她属蛇。
准提幼儿园地址在什么地方,想过去办事
上联开酒喝伤悲。下联是什么好呢?大神求解
卓文君有那些文学作品传世
泥土的大地可以成为那么美好的纸张是什么修辞
男人亲亲吻女人的手,代表什么?
请大师指点,我台车开着无端端这灯会亮是什么
南亚包括哪些国家地区
云南泓联盛嘉房地产开发有限公司怎么样?
搞软件好还是搞硬件好
推荐资讯
物理中的 “吃水线”是什么意思
从什么时候开始黑户法人代表列入失信名单
有带新手的吗
归城曹家村怎么去啊,我要去那办事
友谊长存是什么意思?
别让眼睛老去阅读答案
阳历1992年9月19号是什么星座
请教诸居士:禅宗人可以供奉密宗千手观音么?
气动冲床操作寸动对冲床有无伤害
万年珠山宾馆地址有知道的么?有点事想过去
鬼泣四小说官方中文版
请问汕头天和心理咨询在哪里?之前看过汕头都
手机登qq时,显示手机磁盘不足,清理后重新登
刺客的套装怎么选啊?