zoukankan      html  css  js  c++  java
  • C#学习笔记(定义属性get&set)

      属性拥有两个类似于函数的块,一个块用于获取属性的值,另一个块用于设置属性的值。这两个块也称为访问器,分别用get和set关键字来定义,可以用于控制对属性的访问级别。可以忽略其中的一个块来创建只读或只写属性(忽略get块创建只写属性,忽略set块创建只读属性)。当然,这仅适用于外部代码,因为类中的其他代码可以访问的数据。还可以在访问器上包含可访问修饰符,例如使get块变成公共的,把set块变成保护的。只有包含其中一个一个块,才能获得有效属性(既不能读取也不能修改的属性没有任何用途)。

      属性的基本结构包括标准的可访问修饰符(public、private等),后跟类名、属性和get块(或set块,或者get块和set块,其中包含属性处理代码)。

    public int myIntProp

    {

      get

      {

        //Property get code.

      }

      set

      {

        //Property set code.

      }

    } 

    1 get关键字

      get块必须有一个属性的返回值,简单的属性一般与私有字段相关联,以控制对这个字段的访问,此时get块可以直接返回该字段的值,例如:

    private int myInt;

    public int myIntProp

    {

      get

      {

        return myInt;

      }

      set

      {

        //Property set code.

      }

    }

      类外部的代码不能直接访问这个myInt字段,私有的,必须使用属性来访问该字段。

    2 set关键字

      set函数以类似的方法把一个值赋给字段。这里使用value表示用户提供的属性值:

    private int myInt;

    public int myIntProp

    {

      get 

      {

        return myInt;

      }

      set

      {

        myInt = value;

      }

    }

      value等于类似与属性相同的值,所以如果属性和字段使用相同的类型,就不必担心数据类型转换了。

      这个简单的属性只能直接访问myInt字段。在对操作进行更多的控制的时候,属性的真正作用才能发挥出来,例如,使用下面的代码实现set块:

    set

    {

      if(value >= 0 && value <= 10)

        myInt = value;

    }

      只用赋给属性的值在1~10之间,才会改myInt。此时,要做一个重要的设计选择:如果使用了无效值,该怎么办:

    • 什么也不做
    • 给字段赋默认值
    • 继续执行,就好像没有发生错误一样,但记录下来该事件,以备将来分析
    • 抛出异常

      一般情况下,后面两个选择效果较好,选择哪个选项取决于如何使用类,以及给用户授予多少控制权。抛出异常给用户提供的控制权相当的大,例如:
    set

    {

      if(value >= 0 && value <= 10)

        myInt = value;

      else

        throw (new ArgumentOutOfRangeException("myIntProp",value,"myIntProp must be assigned a value between 0 and 10."))

    }

      这可以在使用属性的代码中通过try...catch...finaly逻辑来处理。

    注:属性可以使用virtual、override和abstract关键字,就像方法一样,但这几个关键字不能用于字段。最后,如上述,访问器可以有自己的访问性。

    实例:

    public class MyClass
    {
    public readonly string Name;
    private int intVal;

    public int Val
    {
      get
      {
      return intVal;
      }
      set
      {
        if (value >= 0 && value <= 10 )
          intVal = value;
        else
          throw (new ArgumentOutOfRangeException("Val",value,"Val must be assigned a value between 0 ang 10."));
      }
    }
    public override string ToString()
    {
      return "Name:"+Name+" Val:"+Val;
    }
    private MyClass(): this("Default Name")
    {

    }
    public MyClass(string newName)
    {
      Name = newName;
      intVal = 0;
    }
    }

    static void Main(string[] args)
    {
      Console.WriteLine("Creating object myobj...");
      MyClass myObj = new MyClass("My Object");
      Console.WriteLine("myObj created.");
      for (int i = -1; i <= 0; i++ )
      {
        try
        {
          Console.WriteLine(" Attempting to assign {0} to myObj.val...",i);
          myObj.Val = i;
          Console.WriteLine("Value {0} assigned to myObj.val.", myObj.Val);
        }
        catch(Exception e)
        {
          Console.WriteLine("Exception {0} throw.",e.GetType().FullName);
          Console.WriteLine("Message: "{0}"",e.Message);
        }
      }
      Console.WriteLine(" Outputting myObj.ToString()...");
      Console.WriteLine(myObj.ToString());
      Console.WriteLine("myObj.ToString() Output.");
      Console.ReadKey();
    }

      Main()中的的代码创建并使用在MyClass.cs中定义的MyClass类的实例。实例化这个类必须使用非默认的构造函数来进行,因为MyClass类的默认构造函数是私有的。

      Main()试着给myObj(MyClass的实例)的Val属性赋值。for循环在两次中赋值-1和0,try..catch...结构用于检测抛出的异常。把-1赋给属性时,会抛出System.ArgumentOutOfException类型的异常,catch块中的代码会把改异常的信息输出到控制台窗口中。在下一个循环中,值0成功的赋给了Val属性,通过这个属性再把值赋给私有字段intVal。

    3 自动属性

      属性是访问对象状态的首选方式,因为他们禁止外部代码实现对象内部的数据存储机制。属性还对内部数据的访问事施加了更多的控制,但是,一般以非常标准的方式属性,即通过一个公共属性来访问一个私有成员。其代码非常类似于前面的代码,这是VS重构工具自动生成的。

      重构功能肯定加快了键入的速度,C#还为此提供了另一种方式:自动属性。利用自动属性,可以用简化的语法声明属性,C#编译器会自动添加未键入的内容,具体而言,编译器会声明一个用于存储属性的私有字段,并在属性的get和set块中使用该字段,我们无需考虑细节。

    public int MyIntProp

    {

      get;

      set;

    }

      我们按照通常的方式定义属性的可访问性、类型和名称。但是没有给get和set块提供实现的代码。这些块的实现代码(和底层的字段)由编译器提供。

      使用自动属性时,只能通过属性访问数据,不能通过底层的私有字段来访问,我们不知道底层私有字段的名称(该名称是编译期间定义的)。但这并不是一个真正意义上的限制,因为可以直接使用属性名。自动属性的唯一限制是他们必须包含get和set存储器,无法使用这种方法定义只读和只写属性。

  • 相关阅读:
    [ python ] 函数的参数
    [ python ] 文件读写操作
    [ python ] 集合的使用
    [ python ] 购物系统
    [ python ] 字符编码
    [ python ] 字典的使用
    [ python ] 列表和元组
    [ python ] 字符串的操作及作业题
    [ python ] 格式化输出、字符集、and/or/not 逻辑判断
    [ python ] 变量及基础的数据类型
  • 原文地址:https://www.cnblogs.com/DannyShi/p/4475726.html
Copyright © 2011-2022 走看看