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+"\nVal:"+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("\nAttempting 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:\n\"{0}\"",e.Message);
    }
  }
  Console.WriteLine("\nOutputting 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存储器,无法使用这种方法定义只读和只写属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值