使用属性替换可访问的数据成员

自1.0版本以来,c#对属性进行了一系列的增强,让其表达能力不断提高。你可以对setter和geter指定不同的访问权限。同时隐式属性也极大降低了声明属性的工作量,不会比声明数据成员麻烦多少。如果你还在类型中声明公有成员,那么快停下来吧,下面我们来对比一下两者的优缺点:

1,属性可以创建出类似于数据访问,但实际上却是方法调用的接口,所以它可以享受到方法调用的所有好处。

2,客户代码访问属性的时候,就像是在访问公有字段,不过其底层使用方法实现,其中还可以自由定义属性访问器的行为。

3,.Net Framework中的数据绑定类仅支持属性,而不支持公有数据成员,对所有的数据绑定类库均是如此,包括WPF,Windows Forms和Silverlight。数据绑定机制将使用反射来找到类型中的特定属性:

textBoxCity.DataBindings.Add("Text",address,"City");这段代码将textBoxCity控件的Text属性绑定到address对象的City属性上。

4,在日后有新的需求或者行为时,属性更易于修改。例如客户要求名称不能为空,若你使用了属性来封装Name,那么只需要修改一处即可:

 public class Customer
    {
        private string name;

        public string Name
        {
            get { return name; }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    throw new ArgumentException("名称不能为空","Name");
                }
                name = value;
            }
        }
    }

但是如果使用了公有数据成员,你就需要查找每一处设置名称的代码并逐一修复。想想这会花费你多少时间。

5,由于属性是使用方法来现实的,所以添加多线程支持也非常简单,很容易在即有的属性的get和set访问器中做出如下修改:

 public class Customer
    {
        private object syncHandle = new object();
        private string name;

        public string Name
        {
            get
            {
                lock (syncHandle)
                    return name;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    throw new ArgumentException("名称不能为空", "Name");
                }
                lock (syncHandle)
                    name = value;
            }
        }
    }

6,属性可以拥有方法的所有语言特性,例如属性可以为虚的(virtual)

      public virtual string Name
        {
            get;
            set;
        }

7,属性的访问器将作为两个独立的方法编译到你的类型中。在c#中,你可以get和set访问器设置不同的访问权限。这样你可以精妙的控制属性暴露出来的数据成员的可见性:

      public virtual string Name
        {
            get;
            protected set;
        }

8,属性的功能很强大,是个不错的改进。但是你是不是还在考虑先用公有数据成员来实现,然后再改成属性呢?这个看似不错的策略,其实却行不通。来看下面的代码:

 public class Customer
    {
        public string Name;
    }

string name=customerOne.Name;
customerOne.Name="Jim";

看似简单直观,你可以认为若是日后将Name改成属性,那么代码可以无需任何修改。但是这个答案并不是完全正确。属性仅仅是在访问时类似于数据成员,但是属性的访问和数据的访问将会生成不同的MSIL语言。所以当你想更新单一程序集变得非常困难。

9,性能比较

若是你查看生成的IL,那么你或许会比较一下两者的性能,属性当然不会比数据成员访问快,不过也不会比它差多少,只要不在属性访问器中执行长时间的计算或者进行跨应用程序的调用(例如执行数据库操作)。

无论何时需要在类型的公有或者保护接口中暴露数据,都应该使用属性,所有的数据成员都应该是私有的,没有任何例外。

对于将变量封装成一个属性所需的额外输入工作其实不会占用太多时间,但是对于今后的维护却带来很大的方便。

时间: 2024-11-05 10:19:20

使用属性替换可访问的数据成员的相关文章

荐读|属性与可直接访问的数据成员之间应该如何选

写在前面 在书写C#代码的时候你是否有过这样的经历:经常混用属性以及公有的数据成员.毕竟他们的用法基本一致,对于使用来说好像没什么区别啊.其实我也经常使用类的公有的数据成员来定义一些常量,为了简单,在一些仅仅需要对外暴露一些常量的类中(如定义一些全局使用的常量),也都是通过定义公有数据成员实现的.直到看到世界世界知名专家Bill Wagner的那本<More Effective C#>之后才意识到应该尽量"使用属性而不是可直接访问的数据成员".因为属性具有修改的便捷性,多线

改善 C# 的语言习惯(一) - 使用属性而不是可访问的数据成员(整理中)

改善 C# 的语言习惯(一) - 使用属性而不是可访问的数据成员 序 为什么我们的程序运行得棒棒的,还要改呢?Why? 答:我们要让程序运行得更快,执行的效率更高,代码的可读性更强,维护的成本更低... .... 我们知道,守旧主义并不适用于计算机行业. 在这里,我会告诉你已经弃用或者应该弃用的东西,并告诉你推荐的用法,以及弃用的原因和推荐使用的原因.

在赋值运算符函数中,类的实例能直接访问私有数据成员???

印象中,private的数据成员只能在类的成员函数中使用,无法通过类的对象直接访问!(错误理解) 正确的理解是:在类的成员函数中,可以直接访问私有成员.即只要在该类的成员函数中,无论是直接访问该类的私有数据成员,还是访问某个对象(必选是该类型)的私有数据成员,均是可以的!!! 借鉴网上(http://blog.csdn.net/iaccepted/article/details/34853937 )的说法就是: 实践证明,类(class)私有成员可以被类成员函数访问,不区分成员在哪个实例(ins

C++静态成员函数和静态数据成员

当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次,而且要被同类的所有对象共享.各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义了多少类对象无关.静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关. 静态数据成员的用途之一是统计有多少个对象实际存在. 静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的.也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一

在c++中,静态数据成员可以被非静态成员函数调用吗?如果可以调用的话那为什么还要定义静态成员函数呢

静态数据成员可以被非静态成员函数访问.但静态成员函数只能访问静态数据成员.静态数据成员从属于某一个类,而不是某一个类的 对象.同理,静态成员函数也是一样. 追问 定义静态成员函数的作用有何在呢 回答 静态成员函数隶属于类,不用实例化对象,就可以直接调用静态成员函数来操作静态数据成员 提问者评价 太给力了,你的回答完美解决了我的问题!

objective-C学习笔记(三)数据成员:属性与实例变量

类型成员 Type Member 结构体 struct 的成员很简单,只有变量. 类的成员就很多了: 数据成员 data member 描述对象(本讲重点) · 实例变量  instance variable · 属性 property 函数成员 function member · 方法 method · 初始化器  init · 析构器  dealloc 类的属性: 默认情况下,编译器会为属性定义propertyName自动合成: 一个getter访问器方法: propertyName 一个s

静态数据成员与静态成员函数

静态属性不是类中每个对象拥有的,而是共有的.由于静态成员逃离了对象而存在的性质,所以该实体应该在所有对象产生之前产生,更适合的时机是在程序启动的时候做初始化.初始化时候不可重复上static,但是要加上类名空间.该实体在程序中的唯一性,要求他不可以和类的定义放在头文件中,但是它确实是类的成员,所以放在类实现中最合适.如下: //--------------------Student.h ---类定义的文件 class Student{ private: static int num; } //-

C++基础(静态数据成员和静态成员函数)

[1.静态成员] 1.静态数据成员与全局变量一样都是静态分配存储空间的,在编译时,就要为类的静态数据成员分配存储空间.但全局变量在程序中的任何位置都可以访问它,而静态数据成员受到访问权限的约束.必须是public权限时,才可能在类外进行访问. 2.静态数据成员的初始化 (1)*静态数据成员的初始化是在类的源文件(.cpp)中,而不是在类的头文件(.h)中进行的.这是因为类声明位于头文件中,程序可能将头文件包括在其他几个文件中.如果在头文件中进行初始化,将出现多个初始化语句副本,从而引发错误. A

转:C语言中的static变量和C++静态数据成员(static member)

转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序运行期间,但作用域与自动变量相同,只能在定义该变量的函数内使用.退出该函数后, 尽管该变量还继续存在,但不能使用它.        b.对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值.而对自动变量不赋初值,则其值是不定的.2).static全局变量        全局变量本身就是静