C# (X):字段,属性,索引器,常量

tips:为什么字段是field

field表示的是一段空间,字段表示的是内存中的一段空间

字段(field)

  1. 什么是字段
    1. 字段是一种表示与对象或类型(类与结构体)关联的变量
    2. 字段是类型的成员
    3. 与对象关联的字段也称之为“实例字段”:表示实例的某状态
    4. 与类型关联的字段也称之为“静态字段”,由static修饰:表示类型的某状态
  2. 字段的声明
    1. 格式:[特性] [修饰符]类型 变量声明器;
      public int age = 100//变量声明器是 age=100,age是变量名,=100是初始化器
      
    2. 字段的声明不是语句
    3. 字段的名字一定是名词
  3. 字段的初始值
    1. 无显示初始化时,字段获得其类型的默认值,所以字段永远不会被初始化
    2. 实例字段初始化:对象创建时
    3. 静态字段初始化:类型被加载时(静态构造器永远只会执行一次)
  4. 只读字段(readonly)
    1. 实例只读字段
    2. 静态只读字段

静态构造器

  class Human 
    {
        public static int Age;

        static Human()//静态构造器 
        {
            Human.Age = 0;
        }

    }

属性(C#特有的概念)

  1. 什么是属性
    1. 属性是一种用于访问对象或者类型的特征的成员,特征反应了状态
    2. 属性是字段的自然拓展
      • 从命名上来看,field更偏向实例对象在内存中的布局,property更偏向于反映现实世界对象中的特征
      • 对外:暴露数据,数据是可以储存在字段里面,也是可以动态计算出来
      • 对内:保护字段不会被非法值污染
    3. 属性由Get/Set方法对进化而来
    4. 属性背后的秘密(又是一个语法糖)
  2. 属性的声明
    //属性声明的格式是[特性] [修饰符] 类型 成员名称 {访问器}
    //完整声明和简略声明的区别就在于如何写{访问器}
    
    1. 完整声明:propfull+tab+tab
    2. 简略声明:prop+tab+tab只用于传递数据
    3. 动态计算值的属性
    4. 注意实例属性和静态属性
    5. 属性的名字一定是名词
    6. 只读属性(几乎没人使用)
  3. 属性和字段的关系
    1. 一般情况下,它们都是用于表示实体(对象或类型)的状态
    2. 属性大多数情况下知识字段的包装器
    3. 建议永远使用属性(而不是字段)来暴露数据,即字段永远都是private或者protected的

属性→字段

将stu3的年龄不小心设置为200,但是平均年龄是80,也符合人的年龄,但是已经为程序引入了一个很难发现的bug,为了避免该情况,可以把Age设置为private,通过Get和Set方法来进行处理

 class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student();
            Student stu2 = new Student();
            Student stu3 = new Student();
            stu1.Age = 20;
            stu2.Age = 20;
            stu3.Age = 200;
            int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
        }
    }
    class Student
    {
        public int Age;
    }

以下是经过处理的程序

 class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student();
            Student stu2 = new Student();
            Student stu3 = new Student();
            stu1.SetAge(20);
            stu1.SetAge(20);
            stu1.SetAge(20);
            int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge());
            Console.WriteLine(avgAge);

        }
    }
    class Student
    {
       private int Age;
        public int GetAge()
        {
            return this.Age;
        }

        public void SetAge(int value )
        {
            if(value >=0 && value <= 120)
            {
                this.Age = value;
            }
            else
            {
                throw new Exception("Age value has error!");
            }
        }
    }

C#经过改进的写法(添加了value上下文关键字set/get访问器

class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student();
            Student stu2 = new Student();
            Student stu3 = new Student();
            stu1.Age = 20;
            stu2.Age = 20;
            stu3.Age = 20;
     
            int avgAge = (stu1.Age+stu2.Age+stu3.Age)/3;
            Console.WriteLine(avgAge);

        }
    }
    class Student
    {
        private int age;
        public int Age
        {
            get//get 访问器
            {
                return this.age;
            }

            set//set访问器
            {
                if (value >= 0 && value <= 120)
                {
                    age = value;
                }
                else
                {
                    throw new Exception("wrong value");
                }
            }
        }
    }

探究属性语法糖

使用ildasm(可以去C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\下找)打开解决方案bin文件夹下的应用程序,展开可以查看最终get和set都是调用了getAge方法

属性的动态计算

CanWork的值会根据不同的Age进行不同的更新

class Student
    {
        private int age;
        
        public int Age
        {
            get//get 访问器
            {
                return this.age;
            }

            set//set访问器
            {
                if (value >= 0 && value <= 120)
                {
                    age = value;
                }
                else
                {
                    throw new Exception("wrong value");
                }
            }
        }

        public bool CanWork 
        { 
            get {
                if (this.age >= 16)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            
            }
        }
    }

索引器(对于初学者很少出现)

  1. 概念:索引器是这样一种成员:它使对象能够用与数组相同的方式(即使用下标)进行索引,使用快捷键indexer + tab + tab
  2. 声明:参见文档,注意没有静态索引器
class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student();
            stu["Math"] = 90;
            var mathScore = stu["Math"];
            Console.WriteLine(mathScore);

        }
    }
    
    class Student
    {
        private Dictionary<string, int> scoreDict = new Dictionary<string, int> { };

        public int? this[string subject]
        {
            get {
                if (this.scoreDict.ContainsKey(subject))
                {
                    return this.scoreDict[subject];
                }
                else
                {
                    return null;
                }
            }
            set {
                if (value.HasValue == false)
                {
                    throw new Exception("Score can not be null");
                }
                if (this.scoreDict.ContainsKey(subject))
                {
                    this.scoreDict[subject] = value.Value;
                }
                else
                {
                    this.scoreDict.Add(subject, value.Value);
                }
            }
        }
    }

常量

  1. 什么是常量
    • 常量是表示常量值的类成员
    • 常量隶属于类型而不是对象,也就是说没有实例常量(“实例常量的角色由制度字段来承担”)
    • 区分成员常量和局部常量
  2. 常量的声明
  3. “只读”的应用场景
    • 为了提高程序可读性和执行效率-常量
    • 为了防止对象的值被更改-只读字段
    • 向外暴露不允许修改的数据-只读属性(静态/非静态),功能和常量有一些重叠
    • 当希望成为常量的值其类型不能被常量声明接收的时候(类/自定义结构体)-静态只读字段

你可能感兴趣的:(C#,c#,开发语言,后端)