• C#:类的成员--属性


    属性的作用

    • 属性是对字段的扩展
    • 使用属性对外能够暴露数据
    • 使用属性对内能够保护字段、使字段不被污染
    • 属性其实是由Get/Set方法对演化而来的

    为什么说属性能够保护字段?

    class Program
    {
        static void Main(string[] args)
        {
            Student student1 = new Student(1);
            student1.name = "xiaoming";
            student1.age = 519;
            Console.WriteLine(student1.name + "  " + student1.age);
    
            Student student2 = new Student(2);
            student2.name = "mike";
            student2.age = -22;
            Console.WriteLine(student2.name + " " + student2.age);
    
            Console.ReadKey();
        }
    }
    
    class Student
    {
        public readonly int id;
        public string name;
        public int age;
    
        public Student(int id)
        {
            this.id = id;
        }
    }
    

    上述在只有字段的程序中,人的年龄在为负数 或者 八百岁显然是不符合实际的。这就是字段被非法数据污染的一种情况
    为了解决这个问题,可以将字段设置成私有字段 然后提供公开的Get和Set方法来设置和获取字段的值

    private int age;
    //注意使用大驼峰命名 Get后面通常是字段的名字
    public int GetAge() 
    {
        return age;
    }
    
    public void SetAge(int value) 
    {
        if (value>=0&&age<=120)
        {
            this.age = value;
        }
        else
        {
            throw new Exception($"{value}不在合法范围内");
        }
    }
    //下面是在Main方法中的调用
    Student student1 = new Student(1);
    student1.SetName("xiaoming");
    student1.SetAge(519);
    Console.WriteLine(student1.GetName() + "  " + student1.GetAge());
    

    运行结果:
    使用Get和Set方法对儿 保护字段
    上面的Get和Set方法在保护字段上,十分有效Java、C++语言现在仍然在广泛地使用;C#语言的研发团队发现这种写法稍稍有些冗长,于是便发明了"属性"的概念,让开发者以属性的访问来间接达到访问字段的效果

    属性的完整写法

    class Program
    {
        static void Main(string[] args)
        {
            Student student1 = new Student(1);
            student1.Name= "xiaoming";
            student1.Age = 19;
            Console.WriteLine(student1.Name + "  " + student1.Age);
    
            Student student2 = new Student(2);
            student2.Name= "mike";
            student2.Age= 22;
            Console.WriteLine(student2.Name + " " + student2.Age);
    
    
            Console.ReadKey();
        }
    }
    
    class Student
    {
        public readonly int id;
        private string name;
        public string Name
        {
            get 
            {
                return name;
            }
    
            set 
            {
                // value在setter包装其中是一个上下文 关键字
                // value 代表给字段设置值时传入的值
                this.name = value;
            }
        }
    
        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                if (value >= 0 && value <= 120)
                {
                    this.age = value;
                }
                else
                {
                    throw new Exception($"{value}不在合法范围内");
                }
            }
        }
        public Student(int id)
        {
            this.id = id;
        }
    }
    

    像使用字段那样使用属性 相较 Get和Set方法对儿 大大减少了程序的冗余

    其实属性的getter和setter是一种语法糖---语法糖就是官方为我们隐藏一些代码,是我们使用起某些功能更加便捷的一种手段。我们可以通过C#的反编译工具来看一下属性包装器背后的秘密。

    • 按下 WIN+R 组合键 输入 ILDASM
      C#反编译工具
    • 将我们程序编译生成的 EXE文件拖入该工具中
      ILDASM反编译工具
    • 双击Name属性可以在新的窗口中看到
      属性包装器内部调用了Get和Set方法
      所以,属性包装器其实是一种语法糖。C#为我们隐藏了Get和Set方法的代码,使我们使用属性更方便。

    属性声明的三种方式及快捷键

    1. 完整声明:借助VisualStuido的代码提示: propfull
      propfull
      以上我们借助代码提示快速完成了属性的完整声明;当然在Set中我们是可以写一些保护字段的逻辑的
    2. 简略声明:同样使用代码提示:prop
      prop
      • 属性的简要声明的使用场景一般使用来传递数据用的;使用简略声明这种格式不能起到保护字段的作用了。
      • 属性简略声明,我们没有声明字段,那么就可以说字段不存在么?不可以:属性的简要声明表面上看我们已经看不到字段的存在了,其实C#已经帮我们创建了字段
        简略声明的属性也会创建字段
    3. 有时我们设计好了程序后,发现只使用了字段而并没有使用属性,此时我们可以使用VS的只能重构方法CTRL+R,E组合键来重构代码。
      快速封装字段

    属性能够动态地计算值 该如何理解?

    class Program
    {
        static void Main(string[] args)
        {
            var student = new Student() { Age = 19, Name = "baobo" };
            Console.WriteLine(student.CanWork);
            Console.ReadKey();
        }
    }
    
    class Student
    {
        private string name;
    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        private int age;
    
        public int Age
        {
            get { return age; }
            set
            {
                age = value;
            }
        }
    
        public bool CanWork
        {
            get
            {
                if (age >= 18)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }
    

    输出结果为:True;上述示例中CanWork属性并未显示封装一个字段,当从外界访问这个属性的时候,所得到的值是实时动态计算出来的
    程序还可以改写成主动地计算值,如下

    class Program
    {
        static void Main(string[] args)
        {
            var student = new Student() { Age = 19, Name = "baobo" };
            Console.WriteLine(student.CanWork);
            Console.ReadKey();
        }
    }
    
    class Student
    {
        private string name;
    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        private int age;
    
        public int Age
        {
            get { return age; }
            set
            {
                age = value;
                // 每当age被赋值的时候 主动去计算 canwork字段的值
                if (age>=18)
                {
                    this.canWork = true;
                }
                else
                {
                    this.canWork = false;
                }
            }
        }
    
        private bool canWork;
    
        public bool CanWork
        {
            get { return canWork; }
        }
    }
    

    总之,属性是比字段要灵活很多的一种函数成员。建议在能使用属性的地方尽可能多地使用属性。以上便是对属性的总结,记录下来以便以后查阅。

  • 相关阅读:
    URL中传参带有%2F等特殊字符
    js根据对象数组中某一属性值,合并相同项,并对某一属性累加处理
    windows传输文件到linux
    npm 切换源
    linux下安装java
    PowerShell:因为在此系统上禁止运行脚本,解决方法
    wget: 未找到命令
    发货通知单禁止手工新增
    固定提前期
    容差码
  • 原文地址:https://www.cnblogs.com/bigbosscyb/p/13702411.html
Copyright © 2020-2023  润新知