鲜荣彬
Herry

  当我们从C语言接触编程开始,一旦定义一个类,我们必然会给这个类定义许多数据成员。然后C#本身却正在极力改变这样一个事实,从各种服务器控件编写你应该可以看出,net对属性的支持远远大于对成员的支持。从我的博客自定义学习控件(一)中你可以看见,当我们自己书写自定义控件时,我们对控件类的定义几乎是属性,而不是数据成员。

  属性本质上为两个函数,get and set函数,而C#的特殊语法一直让我们可以像访问成员一样访问它。因此我们可以在属性的设计上添加更多灵活地内容。get函数让我们返回一个值,而set函数让我们设定返回的值。

  如下,我们定义一个Person类,代码如下(小提示,当我们写了字段后,如何快速写出其属性呢,选择 name ,然后ctrl+r+e,点击确定,就快速写出属性了)

  图1.1

public class Person
    {
        private string name;

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

  当一个类不写任何访问修饰符时,默认的访问权限是internal,而不是所谓的sealed。 这个类的属性Name既有读也有写属性。为什么说get和set是两个函数呢。当然也有人这样写

public string Name
{
    get { returen this.name; }
    set { this.name=value;   }
}

  虽然这样写比上面明了许多,但仍不够明确。其实,查看IL,可以知道,IL为我们生成了get_Name与set_Name两个函数,截图如下。

  图 1.2

  那么,属性和字段的区别是什么呢?个人理解,属性就是对字段的封装。因为微软告诉我们了,图1.1就可以看到。

  使用属性充分体现了对象的封装性:不直接操作类的数据内容,而是通过访问器进行访问,即借助于get和set对属性的值进行读写;另一方面还可以对数据的访问属性进行控制。举个例子,如果你不希望某个字段的值大于5,就可以在属性的set函数中,此进行逻辑控制。那么这比直接对字段进行控制有什么好处呢?个人理解,如果你希望重用某个类,而不是仅仅用一两次(虽然我暂时用的比较少,但是在工作中却用到过,比如用ascx文件,往这个用户控件中某个属性传递参数)。

  其实,属性似乎还有这样一个作用,可以绑定数据,这一定我们可以从TextBox这些控件中可以看出来,而字段却不能绑定数据,但是可以存储数据。

  我们经常听到抽象类,抽象属性你却可能极少听到。没错,有抽象属性,却没有抽象字段。有了抽象属性,这为我们设计出兼容性更强,扩展性更强的类提供了好的解决方案。请看下面一个例子。

public abstract class Sharp
    {
       private string name;
       public string SharpName
       {
           get
           {
               return name;
           }
           set
           {
               name = value;
           }
       }
       public Sharp(string s)
       {
           SharpName = s;
       }

       public abstract double Area
       {
           get;
       }

       public override string ToString()
       {
           return SharpName + " Area=" + string.Format("{0:F2}", Area);
       }

  在这个类中,我们有一个抽象属性面积Area,只读属性。然后有个私有字段name(用于记录该形状的名称),一个公共属性,还重写了ToString()函数,返回该图形的面积。

  下面两个类,一个正方形,一个圆形,继承了该图形形状类,代码如下

public class Square:Sharp
    {
        private int side;
        public Square(int side, string SharpName)
            : base(SharpName)
        {
            this.side = side;
        }

        public override double Area
        {
            get { return side * side; }
        }
    }

 public class Circle:Sharp
    {
        private int radius;
        public Circle(int radius, string SharpName)
            : base(SharpName)
        {
            this.radius = radius;
        }

        public override double Area
        {
            get {
                return radius * radius * System.Math.PI;
            }
        }

  在这两个类中,我们重写了抽象属性Area,分别计算正方形和圆形的面积。我们只需要往该类中传入该图形的特有的属性如边长,半径,就可得到面积。

            Sharp[] shapes =
            {
                new Square(5,"Square"),
                new Circle(3,"Circle")
            };

            foreach (Sharp item in shapes)
            {
                Console.WriteLine(item);
            } 

  这种代码的书写简便灵敏,减少代码数量,有一点点小小的设计模式的味道。

  公共成员与属性虽然调用的语法都是 对象名.Area或对象名.MyName,但是IL语言上却是不通的,属性调用的是get_Area()方法,而成员调用的则是这个字符串所存储的数据。

  属性和数据成员这两个东西,说白了就是属性封装了数据成员,让我们了解面向对象的含义。虽然大多数.net程序员实际编程过程中,还是面向过程编程,这的确是一种避免不了的事实,小型企业利润还是首要的,软件能用就行。

  

posted on 2013-03-17 18:34  Herry彬  阅读(5797)  评论(1编辑  收藏  举报