9.2 属性 - 图1
建议:永远使用属性(而不是字段)来暴露数据,即字段永远是 private 或 protected 的。
字段只在类内部使用,类之间交换数据,永远只用属性。

什么是属性

使用 Get/Set 方法对之前:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var stu1 = new Student()
  6. {
  7. Age = 20
  8. };
  9. var stu2 = new Student()
  10. {
  11. Age = 20
  12. };
  13. var stu3 = new Student()
  14. {
  15. // 非法值,污染字段
  16. Age = 200
  17. };
  18. var avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
  19. Console.WriteLine(avgAge);
  20. }
  21. }
  22. class Student
  23. {
  24. public int Age;
  25. }

使用 Get/Set 后:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. Student stu1 = new Student();
  8. stu1.SetAge(20);
  9. Student stu2 = new Student();
  10. stu2.SetAge(20);
  11. Student stu3 = new Student();
  12. stu3.SetAge(200);
  13. int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge()) / 3;
  14. Console.WriteLine(avgAge);
  15. }
  16. catch (Exception ex)
  17. {
  18. Console.WriteLine(ex.Message);
  19. }
  20. }
  21. }
  22. class Student
  23. {
  24. private int age;
  25. public int GetAge()
  26. {
  27. return this.age;
  28. }
  29. public void SetAge(int value)
  30. {
  31. if (value >= 0 && value <= 120)
  32. {
  33. this.age=value;
  34. }
  35. else
  36. {
  37. throw new Exception("Age value has error.");
  38. }
  39. }
  40. }

使用 Get/Set 来保护字段的方法至今仍在 C++、JAVA 里面流行(即 C++、JAVA 里面是没有属性的)。
因为 Get/Set 写起来冗长,微软应广大程序员请求,给 C# 引入了属性。

引入属性后:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. Student stu1 = new Student();
  8. stu1.Age = 20;
  9. Student stu2 = new Student();
  10. stu2.Age = 20;
  11. Student stu3 = new Student();
  12. stu3.Age = 200;
  13. int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
  14. Console.WriteLine(avgAge);
  15. }
  16. catch (Exception ex)
  17. {
  18. Console.WriteLine(ex.Message);
  19. }
  20. }
  21. }
  22. class Student
  23. {
  24. private int age;
  25. public int Age
  26. {
  27. get
  28. {
  29. return this.age;
  30. }
  31. set
  32. {
  33. if (value >= 0 && value <= 120)
  34. {
  35. this.age = value;
  36. }
  37. else
  38. {
  39. throw new Exception("Age value has error.");
  40. }
  41. }
  42. }
  43. }

引入属性后代码简洁明了许多。

静态属性:

  1. namespace tttlll
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. try
  8. {
  9. Student.Amount = -100;
  10. Console.WriteLine(Student.Amount);
  11. }
  12. catch (Exception ex)
  13. {
  14. Console.WriteLine(ex.Message);
  15. }
  16. }
  17. }
  18. class Student
  19. {
  20. private static int amount;
  21. public static int Amount
  22. {
  23. get { return amount; }
  24. set
  25. {
  26. if (value >= 0)
  27. {
  28. Student.amount = value;
  29. }
  30. else
  31. {
  32. throw new Exception("Amount must greater than 0.");
  33. }
  34. }
  35. }
  36. }

属性的声明

Code Snippet

  1. prop + 2 * TAB:属性的简略声明
  2. propfull + 2 * TAB:属性的完整声明
  3. private int age;

(1)用鼠标点击age,点击编辑→重构→封装字段 (2)将光标放在age上,Ctrl+RE

图片.png
图片.png图片.png
图片.png

动态计算值的属性

主动计算,每次获取 CanWork 时都计算,适用于 CanWork 属性使用频率低的情况。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. Student stu = new Student();
  8. stu.Age = 12;
  9. Console.WriteLine(stu.CanWork);
  10. }
  11. catch (Exception ex)
  12. {
  13. Console.WriteLine(ex.Message);
  14. }
  15. }
  16. }
  17. class Student
  18. {
  19. private int age;
  20. public int Age
  21. {
  22. get
  23. {
  24. return age;
  25. }
  26. set
  27. {
  28. age = value;
  29. }
  30. }
  31. public bool CanWork
  32. {
  33. get
  34. {
  35. if (this.age>=16)
  36. {
  37. return true;
  38. }
  39. else
  40. {
  41. return false;
  42. }
  43. }
  44. }
  45. }

被动计算,只在 Age 赋值时计算一次,适用于 Age 属性使用频率低,CanWork 使用频率高的情况。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. try
  6. {
  7. Student stu = new Student();
  8. stu.Age = 12;
  9. Console.WriteLine(stu.CanWork);
  10. }
  11. catch (Exception ex)
  12. {
  13. Console.WriteLine(ex.Message);
  14. }
  15. }
  16. }
  17. class Student
  18. {
  19. private int age;
  20. public int Age
  21. {
  22. get
  23. {
  24. return age;
  25. }
  26. set
  27. {
  28. age = value;
  29. this.CalculateCanWork();
  30. }
  31. }
  32. private bool canWork;
  33. public bool CanWork
  34. {
  35. get { return canWork; }
  36. }
  37. private void CalculateCanWork()
  38. {
  39. if (this.age>=16)
  40. {
  41. this.canWork = true;
  42. }
  43. else
  44. {
  45. this.canWork = false;
  46. }
  47. }
  48. }