C#基礎語法 — (7)字段、屬性、索引器、常量


在這裏插入圖片描述

一、字段

在這裏插入圖片描述

1.實例字段與靜態字段

  實例字段與對象相關聯
  靜態字段與類型相關聯,由static修飾

    class Program
    {
        static void Main(string[] args)
        {                  
            List<Student> stuList = new List<Student>();
            for (int i = 0; i < 100; i++)
            {
                Student stu = new Student();
                stu.Age = 24;
                stu.Score = i;
                stuList.Add(stu);
            }
            Student.ReportAmount();//學生人數


            int totalAge = 0;
            int totalScore = 0;
            foreach (var stu in stuList)
            {
                totalAge += stu.Age;
                totalScore += stu.Score;
            }
            Student.AverageAge = totalAge / Student.Amount;//學生平均年齡
            Student.AverageScore = totalScore / Student.Amount;//學生平均成績

            Student.ReportAverageAge();
            Student.ReportAverageScore();
        }
    }

    class Student
    {
        //實例字段
        public int Age;
        public int Score;

        //靜態字段   
        public static int AverageAge;
        public static int AverageScore;
        public static int Amount;

        public Student()
        {
            Student.Amount++;
        }

        public static void ReportAmount()
        {
            Console.WriteLine(Student.Amount);
        }

        public static void ReportAverageAge()
        {
            Console.WriteLine(Student.AverageAge);
        }

        public static void ReportAverageScore()
        {
            Console.WriteLine(Student.AverageScore);
        }
    }

2.字段的聲明

字段(field)是一種表示與對象或類關聯的變量的成員。

  • 對於實例字段,它初始化的時機是在實例創建時
    • 聲明實例字段時初始化值與在實例構造器裏面初識化實例字段是一樣的
  • 對於靜態字段,它初始化的時機是在運行環境加載該數據類型時
    • 即靜態構造器初始化時
    • 聲明靜態字段時設置初始化值與在靜態構造器裏面初始化靜態字段其實是一樣的

數據類型被運行環境加載時,它的靜態構造器將會被調用,且只被調用一次。

實例構造器 與 靜態構造器:

    class Student
    {
        //實例字段
        public int Age = 0;
        public int Score;

        //靜態字段   
        public static int AverageAge;
        public static int AverageScore;
        public static int Amount;

        //實例構造器
        public Student()
        {
          
        }

        //靜態構造器
        static Student()
        {
            
        }
    } 

3.只讀字段 readonly

  只讀字段只能初始化,無法賦值
  只讀字段爲實例或類型保存一旦初始化後就不希望再改變的值。

①只讀實例字段

    class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student(1);
            Console.WriteLine(stu1.ID);          
        }
    }


    class Student
    {
        //實例字段
        public readonly int ID;//只讀實例字段      
        
        //實例構造器
        public Student(int id)
        {
            this.ID = id; //只讀字段只能初始化,無法賦值
        }      
    } 

②只讀靜態字段

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Brush.DefaultColor.Red);
            Console.WriteLine(Brush.DefaultColor.Green);
            Console.WriteLine(Brush.DefaultColor.Blue);
        }
    }

    struct Color
    {
        public int Red;
        public int Green;
        public int Blue;
    }

    class Brush
    {
        //類的靜態只讀字段
        public static readonly Color DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };

        //public static readonly Color DefaultColor;       
        //static Brush()
        //{
        //    Brush.DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };
        //}
    }

二、屬性

在這裏插入圖片描述
注:永遠使用屬性(而不是字段)來暴露數據,即字段永遠是 private 或 protected 的。
  字段只在類內部使用,類之間交換數據,永遠只用屬性。

1.什麼是屬性

①使用 Get/Set 方法對之前

    class Program
    {
        static void Main(string[] args)
        {
            Student stu1 = new Student();
            stu1.Age = 20;

            Student stu2 = new Student();
            stu2.Age = 20;

            Student stu3 = new Student();
            stu3.Age = 200;//非法值,污染字段

            int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
            Console.WriteLine(avgAge);
        }
    }

    class Student
    {
        public int Age;       
    }

☆②使用 Get/Set 方法對之後

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu1 = new Student();
                stu1.SetAge(20);

                Student stu2 = new Student();
                stu2.SetAge(20);

                Student stu3 = new Student();
                stu3.SetAge(200);

                int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge()) / 3;
                Console.WriteLine(avgAge);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }            
        }
    }

    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!");
            }
        }
    }

  使用 Get/Set 來保護字段的方法至今仍在 C++、JAVA 裏面流行(即 C++、JAVA 裏面是沒有屬性的)。
  因爲 Get/Set 寫起來冗長,微軟應廣大程序員請求,給 C# 引入了屬性。

☆③引入屬性後

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu1 = new Student();
                stu1.Age = 20;

                Student stu2 = new Student();
                stu2.Age = 20;

                Student stu3 = new Student();
                stu3.Age = 200;

                int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
                Console.WriteLine(avgAge);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {
        private int age;
        public int Age
        {
            //訪問器set/get
            get
            {
                return this.age;
            }

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

2.屬性的聲明

在這裏插入圖片描述

1. prop + 2 * TAB:屬性的簡略聲明
2. propfull + 2 * TAB:屬性的完整聲明

(1)屬性的完整聲明

①實例屬性的聲明

  實例屬性表示的是實例的某個數據

 	 class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu1 = new Student();
                stu1.Age = 20;

                Student stu2 = new Student();
                stu2.Age = 20;

                Student stu3 = new Student();
                stu3.Age = 200;

                int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
                Console.WriteLine(avgAge);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {
        private int age;
        public int Age
        {
            //訪問器set/get
            get
            {
                return this.age;
            }

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

②靜態屬性的聲明

  靜態屬性表示的是類型當前的數據

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student.Amount = -100;
                Console.WriteLine(Student.Amount);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {       
        private static int  amount;

        public static int Amount
        {
            get { return amount; }
            set {
                if (value>=0)
                {
                    Student.amount = value;
                }
                else
                {
                    throw new Exception("Age value has error");
                }
            }
        }
    }

(2)屬性的簡略聲明

  簡略聲明的屬性,功能上與一個公有的字段一樣

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu = new Student();
                stu.Age = 100;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {           
        public int Age { get; set; }
    }

(3)VS高級版(企業版)屬性的聲明

快捷鍵:Ctrl + R + E
編輯 → 重構→封裝字段
在這裏插入圖片描述

☆3.動態計算值的屬性

  主動計算,每次獲取 CanWork屬性 時都計算,適用於 CanWork 屬性使用頻率低的情況。

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu = new Student();
                stu.Age = 18;
                Console.WriteLine(stu.CanWork);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }


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

  被動計算,只在 Age 賦值時計算一次,適用於 Age 屬性使用頻率低,CanWork屬性 使用頻率高的情況。

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Student stu = new Student();
                stu.Age = 18;
                Console.WriteLine(stu.CanWork);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    class Student
    {
        private int age;

        public int Age
        {
            get { return age; }
            set
            {
                age = value;

                this.CalculateCanWork();
            }

        }


        private bool canWork;

        public bool CanWork
        {
            get
            {
                return canWork;
            }
        }

        private void CalculateCanWork()
        {
            if (this.age >= 15)
            {
                this.canWork = true;
            }
            else
            {
                this.canWork = false;
            }
        }
    }

三、索引器

在這裏插入圖片描述

index + 2 * TAB:快速聲明索引器

  索引器一般都是用在集合上面,像如下示例這樣用法是很少見的

    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> scoreDictionary = new Dictionary<string, int>();

        public int? this[string subject]
        {
            get
            {
                if (this.scoreDictionary.ContainsKey(subject))
                {
                    return this.scoreDictionary[subject];
                }
                else
                {
                    return null;
                }

            }
            set
            {
                if (value.HasValue == false)
                {
                    throw new Exception("Score cannot be null.");
                }

                if (this.scoreDictionary.ContainsKey(subject))
                {
                    this.scoreDictionary[subject] = value.Value;//  可空類型的 Value 屬性纔是其真實值。
                }
                else
                {
                    this.scoreDictionary.Add(subject, value.Value);
                }
            }
        }
    }

四、常量

在這裏插入圖片描述
在這裏插入圖片描述

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(WASPEC.WebsiteURL);
        }

        class WASPEC
        {
            //成員常量
            public const string WebsiteURL = "http://www.waspec.org"; 
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(WASPEC.WebsiteURL);
        }

        class WASPEC
        {
            public const string WebsiteURL = "http://www.waspec.org";
            public static readonly Building Location = new Building("Score Address");//靜態只讀字段
        }

        class Building
        {
            public Building(string address)
            {
                this.Address = address;
            }

            public string Address { get; set; }
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章