【Unity|C#】基础篇(7)——属性(Property)/ 索引器(Indexer)

【学习资料】

        > 在线文档

            官方文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/

            菜鸟教程(高级教程):https://www.runoob.com/csharp/csharp-tutorial.html

        > 视频教程

            腾讯学院、Siki学院

        > 书籍 

    《C#图解教程》(第6章):https://www.cnblogs.com/moonache/p/7687551.html

 

【学习内容】 

  > 菜鸟教程:高级教程部分(属性、索引器)

  > 《C#图解教程》:第六章

 


【属性Property】

  • 使用属性的原因
    • 隐藏 类外部对类的某 成员数据(_age) 进行 直接操作,将_age设置为私有成员数据  private int _age = 0; 
    • set/get访问器中赋值或获取值时,可以加入其他代码逻辑(如数值范围大小限制)
    • 对类外部只开放 只读只写 权限
    • class Person
      {
          private int _age = 0;   // 字段:分配内存
          public int Age          // 属性:不分配内存
          {
              get { return _age; }
              set { _age = value; }
          }
      }

 

  • 属性是一个特殊的成员函数,包含了:set get 访问器
    • 属性不分配内存
    • set访问器
      • 拥有一个单独的、隐式的值参,名称为 value,与属性的类型相同
      • 拥有一个返回类型void
    • get访问器
      • 没有参数
      • 拥有一个与属性类型相同的返回类型
    • 例如:定义一个Age属性
    • class Person
      {
          private int _age = 0;   // 字段:分配内存
          public int Age          // 属性:不分配内存
          {
              get // get访问器, 要有return
              {
                  return _age;
              }
              set // set访问器, 包含隐藏参数value
              {
                  if (value < 0) // 访问器里可以对value进行校验
                  {
                      _age = 0;
                      Debug.Log("年龄输入有误");
                  }
                  else
                      _age = value;
              }
          }
      }
      void Start()
      {
          Person person = new Person();
          person.Age = 18;
          Debug.Log(person.Age);
      }

 

  • 属性的访问权限
    • 属性可以只有set或get访问器:属性只读或只写
      • 只有set访问器:只写属性,此时  Debug.Log(person.Age);  就无法访问了;
      • class Person
        {
            private int _age = 0;   // 字段:分配内存
            public int Age          // 属性:不分配内存
            {set // set访问器, 包含隐藏参数value
                {
                    if (value < 0) // 访问器里可以对value进行校验
                    {
                        _age = 0;
                        Debug.Log("年龄输入有误");
                    }
                    else
                        _age = value;
                }
            }
        }
      • 只有get访问器:只读属性,此时 person.Age = 18;  就无法设置了;
      • class Person
        {
            private int _age = 0;   // 字段:分配内存
            public int Age          // 属性:不分配内存
            {
                get // get访问器, 要有return
                {
                    return _age;
                }
            }
        }
    • 属性的set和get可以加访问修饰符: private  protected   internal 
      • class Person
        {
            private int _age = 0;   // 字段:分配内存
            public int Age          // 属性:不分配内存
            {
                get // get访问器, 要有return
                {
                    return _age;
                }
                private set // 定义成私有set访问器, 只有类内部可以访问
                {
                    if (value < 0) // 访问器里可以对value进行校验
                    {
                        _age = 0;
                        Debug.Log("年龄输入有误");
                    }
                    else
                        _age = value;
                }
            }
            // 私有属性set访问器,类内部可访问
            public void UpdateAge(int age)
            {
                Age = age;
            }
        }
        void Start()
        {
            Person person = new Person();
            //person.Age = 18;  // 报错,私有属性set访问器,外部无法访问
            Debug.Log(person.Age);
        }

 

  •  自动实现属性
    • 只声明set和get,编译器会自动创建隐藏的数据
    • class Person
      {
          public int Age  // 属性:分配内存(会自动创建隐藏数据)
          {
              get;
              private set;
          }
      }

 

  • 抽象属性
    • 属性也可以定义为抽象属性(与抽象函数类似)
    • public abstract class Person
      {
          public abstract int Age // 抽象属性,与抽象函数类似
          {
              get;
              set;
          }
      }
      class Student : Person
      {
          public override int Age // 子类实现
          {
              get;
              set;
          }
      }
      void Start()
      {
          Person student = new Student();
          student.Age = 18;
          Debug.Log(student.Age);
      }

 


【索引器Indexer】

  •  定义
    • 与 属性 功能基本相似,也是用set和get访问器实现,但是通过 类似数组下标[index] 的方式进行访问,相当于一个 虚拟数组
    • 和属性一样,索引器也不用分配内存来存储
    • return-type this[int index] 
      {
         // get 访问器
         get 
         {
            // 返回 index 指定的值
         }
         // set 访问器
         set 
         {
            // 设置 index 指定的值 
         }
      }

 

  •  例子:内部定义数组  private string[] namelist ,然后通过索引器访问
    • class IndexedNames
      {
          static public int size = 5;
          private string[] namelist = new string[size];
      
          // 定义索引器,下标类型为[int]
          public string this[int index]
          {
              get
              {
                  if (index >= 0 && index < size)
                  {
                      return namelist[index];
                  }
                  else
                  {
                      Debug.Log("index超出范围");
                      return "";
                  }
              }
              set
              {
                  if (index >= 0 && index < size)
                  {
                      namelist[index] = value;
                  }
              }
          }
      }
      void Start()
      {
          IndexedNames names = new IndexedNames();
          names[0] = "Zara"; // 索引器[0]
          names[1] = "Riz";  // 索引器[1]
      }

 

  •  索引器重载
    • 可以是不同的类型可以有多个参数
    • int类型: public string this[int index] 
    • string类型: public int this[string name] 
    • 多参数类型: public string this[int index1, int index2] 
      • 访问方式:names[index1, index2]
      • 注:names[index1][index2] 相当于执行 [int index]  获取到nameList[index1],然后读取string的第index2的字符
    • class IndexedNames
      {
          static public int size = 5;
          private string[] namelist = new string[size];
          // 
          public string this[int index]
          {
              get
              {
                  if (index >= 0 && index < size)
                  {
                      return namelist[index];
                  }
                  else
                  {
                      Debug.Log("index超出范围");
                      return "";
                  }
              }
              set
              {
                  if (index >= 0 && index < size)
                  {
                      namelist[index] = value;
                  }
              }
          }
          // 多参数[index1, index2]: 例如index2表示获取子串长度
          // 访问方式names[index1, index2],而不是names[index1][index2]
          public string this[int index1, int index2]
          {
              get
              {
                  return namelist[index1].Substring(0, index2);
              }
          }
          // [string] 获取name对应的下标index
          public int this[string name]
          {
              get
              {
                  int index = -1;
                  for (int i = 0; i < namelist.Length; ++i)
                  {
                      if (namelist[i] == name)
                      {
                          index = i;
                          break;
                      }
                  }
                  return index;
              }
          }
      }
      void Start()
      {
          IndexedNames names = new IndexedNames();
          names[0] = "Alice";     // 索引器[0]
          names[1] = "Bob";       // 索引器[1]
          names[2] = "Cherry";    // 索引器[2]
          Debug.Log(names[0]);    // 输出:Alice
          Debug.Log(names["Bob"]);// 输出:1
          Debug.Log(names[2, 3]); // 输出:Che
          Debug.Log(names[2][5]); // 输出:r
      }

       

 

你可能感兴趣的:(【Unity|C#】基础篇(7)——属性(Property)/ 索引器(Indexer))