• 属性(property) VS 数据成员(field)


    对于可访问的数据成员(指的是类外部可以访问),就是指在类中,用public修饰的简单的公共变量。

    而属性,要比这个复杂得多,同时,自从1.0以来,C#对属性进行了一系列的增强,属性愈发强大。

    1. 从概念上讲

    属性是对私有字段的访问进行封装,它提供了对私有字段灵活的读、写和计算操作。在C#中,我们通过get和set访问器来实现对属性的读和写操作。

    2. 从本质上来说

    属性让我们可以创建出类似于数据访问,也就是说,我们对属性的操作,跟对数据成员的操作时很类似的。但是,属性事实上是一个方法。

    假设我们有一个Address的类如下:

    public class Address
        {
            public string State { get; set; }
    
            public string City;
        }

    其中State是属性,而City是公开的数据成员,如果我们进行如下调用:

                Address address = new Address();
                address.State = "NY";//property
                address.City = "New York";//field
                Console.WriteLine("I live in :"+address.State+" "+address.City);
                Console.ReadLine();
     
    通过查看IL代码,我们可以发现,对于address.State=”NY”的操作,实际上是调用一个叫做set_State(string) 的方法,同样的,对于读取操作的address.State,实际上是调用get_State() 方法:
     
    //address.State = "NY";对应的IL代码
    callvirt instance void ConsoleApplicationTest.Entity.Address::set_State(string) 
     
    //address.State对应的IL代码:
    callvirt instance string ConsoleApplicationTest.Entity.Address::get_State() 
     
    //address.City = "New York";对应IL代码
    ldstr "New York"
    stfld string ConsoleApplicationTest.Entity.Address::City
     
    //address.City对应的IL嗲吗
    ldfld string ConsoleApplicationTest.Entity.Address::City
     
    也就是说,属性能够以方法调用的形式访问或修改内部数据,成员函数中可以实现的功能均可以在属性中实现。
     
     
    3. 灵活性
     
    属性相对于普通的数据成员来说,具有跟高的灵活性。特别是当我们有新的需求或行为时。
    假设我们有一个Customer类,如下:
     
    public class Customer
        {
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
        }

     

    但是,我们可能很快就会有这样的需求,客户的名字是不能赋值为空的,对于属性,我们可以很方便的修改如下:

    public class Customer
        {
            private string name;
            public string Name
            {
                get { return name; }
                set
                {
                    if(string.IsNullOrEmpty(name))throw new ArgumentException("Name cannot be blank","Name");
                    name = value;
                }
            }
        }

    而对于使用属性的地方,我们根本不用去修改它。

    试想一下,如果我们不是使用属性,而是使用字段,天晓得我们需要修改多少地方呢?

    同时,我们还可以在get和set中封装一些逻辑,从而保证数据的读写是安全的,而公有的数据成员,我们可能会产生一些不安全的操作,如数组越界等。

     

    4. 读和写操作的访问权限的限制

    对于属性,我们可以设定其读和写设定不同的访问权限,具体方法就是通过在get和set前面加上protected或public等。

     

    5. 将数据成员改成属性

    虽然属性和数据成员在使用上是兼容的,但是在二进制层面却大相径庭。如果我们将某个数据成员改成属性,那么就必须重新编译所有用到该公有数据成员的代码。

     

    6. 性能

    数据成员访问虽然在性能上会更快一些。但是,JIT编译器将内联一些方法调用,包括属性访问器。当JIT编译器内联了属性访问器时,两者的访问效率基本就可以持平了。即使某个属性访问器没有被内联,属性相对于数据成员访问,仅仅多了一个方法调用而已,因此,二者的性能差别也是微乎其微的。

     

    7. 书写上

    也许你会说,属性的书写较数据成员更麻烦,事实上,在VS的IDE中,键入prop,然后按TAB建,便会自动输出public TYPE Type { get; set; },然后你只需要将TYPE和Type改成实际需要的就可以了。书写起来一点也不麻烦。

     

    因此,无论何时,需要在类型的公有或保护接口中暴露数据,我们都应该使用属性(property),而不是数据成员(field)。这也是微软推荐的做法。

  • 相关阅读:
    MSchart设置网格线
    搭建ELDK交叉编译环境
    Virtualbox设置共享文件夹的方法
    VS2010自动关闭问题的解决方法
    如何让PHPCms内容页支持JavaScript
    Phpcms V9 调用全站最新文章的代码
    Phpcms V9 调用随机文章的方法
    VMware下Ubuntu不能和主机共享文件夹的解决方法
    Xshell无法连接Ubuntu的解决办法
    Phpcms V9 调用全站文章排行的解决方案
  • 原文地址:https://www.cnblogs.com/tian2010/p/2509030.html
Copyright © 2020-2023  润新知