您的位置:首页 > 编程语言 > C#

天轰穿C# -vs2010 - 04面向对象的编程之属性【原创】

2012-12-27 15:15 375 查看
老田:这就需要用属性了。而属性的使用和字段有很大的相似之处。如下例:

创建Windows桌面应用程序;

添加类Product,代码如下:

using System;

using System.Text;

namespace _4_5_ProductManagr

{

public class Product

{

///<summary>

///商品名 这是VS能够认识的字段的注释方式

///</summary>

private string _name;

// 价格 这种注释方式VS无法认识,也就无法提供智能提示

private decimal _price;

// 颜色

private string _color;

///<summary>

///商品名称,可读可写 这是VS能够认识的属性的注释方式

///</summary>

public string Name

{

get { return _name; } //可读

set { _name = value; } //可写

}

///<summary>

///价格,只写,不允许读

///</summary>

public decimal Price

{

set { _price = value; } //可写

}

///<summary>

///颜色,只读不可写

///</summary>

public string Color

{

get { return _color; } //可读

}

}

}

在Form1的界面上做图4-16,这里就不详细讲了,如果你前面的每个示例都清楚命名习惯的话,完全猜得出来



图4-16

双击“添加”按钮,在按钮中添加代码,使按钮事件代码如下:

private void button1_Click(object sender, EventArgs e)

{

Product pd = new Product(); //实例化 pd 对象

pd.Name = tb_name.Text;

pd.Price = decimal.Parse(tb_price.Text);

pd.Color = tb_Color.Text; //这行代码出错,为什么?

//添加完成后,填充下面预览的模块

lbl_name.Text = pd.Name;

lbl_price.Text = pd.Price.ToString(); //这行代码出错,为什么?

lbl_color.Text = pd.Color;

}

上面代码中因为读写权限导致有两行代码出错,请问如何修正?

小天:多简单啊,在添加的时候先对所有属性进行写操作(set),接着在预览中有全部进行读操作(get)。但是在Product中Price属性是只写不许读,所以下面预览这里会出错,而Color是只读不许写,所以赋值的时候就出错了。所以要把这个例题修正的话,只需要为Price和Color这两个属性完善读写权限即可。

老田:是的,从上面例题,可以总结出,属性的第一个最大作用就是控制读写权限。这是访问修饰符办不到的。所以我们不会考虑将字段公开来做属性。

属性还有一个重要的特性,代码如下:

// 商品名

private string _name;

///<summary>

///商品名称

///</summary>

public string Name

{

get { //在向用户返回值之前检测

if (_name == "")

return "商品暂无名字";

else

return _name;

}

set { //在向字段写入值之前检测

if (value == "")

_name = "想骗我?不行的啦!";

else

_name = value;

}

}

小天:这个示例也简单,就是在向类中的数据字段读写值的之前先检查。不过我有点没有看懂,就是这里面的value是哪里来的??

老田:get访问器不带参数,且必须返回属性声明的类型。也不应为set访问器指定任何显式参数,但编译器假定它带一个参数,其类型也与属性相同,并表示为value。

最后一个重要提醒。访问对象的属性,在属性名后面不加括号,访问类中的方法就一定要加括号。例如

lbl_name.Text = pd.Name; //Name是属性

lbl_price.Text = pd.Price.ToString(); //ToString是方法

小天:我怎么知道谁是属性,谁是方法呢??

老田:看下图4-17你就明白了。



图4-17

实现属性还有种办法,如果属性的set和get访问器中没有任何逻辑,就可以使用自动实现的属性。这种属性会自动实现基础成员变量。上例的代码如下:

public string Name {get; set;}

小天:你的意思是,使用这种方式则可以不在显示的申明private string _name这个成员变量。编译器会自动创建它。

老田:是的,但是使用自动实现的属性,就不能在属性设置中进行属性的有效性验证。所以在上面的例子中,不能检查_name是否为空。但必须同时设置读写两个访问器。尝试把该属性设置为只读属性,就会出错:

public string Name {get; }

但是,每个访问器的访问级别可以不同。因此,下面的代码是合法的:

public string Name {get; private set;}

小天:通过属性访问字段,而不是直接访问字段。这些额外的函数调用是否会增加系统开销,导致性能下降?

老田:不需要担心这种编程方式会在C#中带来性能损失。C#代码会编译为IL,然后在运行期间进行正常的JIT编译,获得内部可执行代码。JIT编译器可生成高度优化的代码,并在适当的时候内联代码(即用内联代码来替代函数调用)。如果某个方法或属性的执行代码仅是调用另一个方法,或返回一个字段,则该方法或属性肯定是内联的。但要注意,在何处内联代码的决定完全由CLR做出。

本文章为天轰穿原创作品,转载请注明出处及作者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐