使用属性(C# 编程指南)

 

C# 编程指南

使用属性(C# 编程指南)

 
与字段不同,属性不作为变量来分类。因此,不能将属性作为 refC# 参考)参数或 outC# 参考)参数传递。
属性具有多种用法:它们可在允许更改前验证数据;它们可透明地公开某个类上的数据,该类的数据实际上是从其他源(例如数据库)检索到的;当数据被更改时,它们可采取行动,例如引发事件或更改其他字段的值。
属性在类模块内是通过以下方式声明的:指定字段的访问级别,后面是属性的类型,接下来是属性的名称,然后是声明 get 访问器和/或 set 访问器的代码模块。例如:
C#
复制代码
public class Date
{
    private int month = 7;  // "backing store"
 
    public int Month
    {
        get
        {
            return month;
        }
        set
        {
            if ((value > 0) && (value < 13))
            {
                month = value;
            }
        }
    }
}
在本例中, Month 是作为属性声明的,这样 set 访问器可确保 Month 值设置为 1 和 12 之间。 Month 属性使用私有字段来跟踪实际值。属性的数据的真实位置经常称为属性的“后备存储”。属性使用作为后备存储的私有字段是很常见的。将字段标记为私有可确保该字段只能通过调用属性来更改。有关公共和私有访问限制的更多信息,请参见 访问修饰符(C# 编程指南)
 get 访问器
get 访问器体与方法体相似。它必须返回属性类型的值。执行 get 访问器相当于读取字段的值。例如,当正在从 get 访问器返回私有变量并且启用了优化时,对 get 访问器方法的调用由编译器进行内联,因此不存在方法调用的系统开销。然而,由于在编译时编译器不知道在运行时实际调用哪个方法,无法内联虚拟 get 访问器。以下是返回私有字段 name 的值的 get 访问器:
C#
复制代码
class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
         get
        {
            return name;
        }
    }
}
当引用属性时,除非该属性为赋值目标,否则将调用 get 访问器以读取该属性的值。例如:
C#
复制代码
Person p1 = new Person();
//...
 
System.Console.Write(p1.Name);  // the get accessor is invoked here
通过使用 get 访问器更改对象的状态不是一种好的编程风格。例如,以下访问器在每次访问 number 字段时都产生更改对象状态的副作用。
C#
复制代码
private int number;
public int Number
{
    get
    {
        return number++;   // Don't do this
    }
}
get 访问器可用于返回字段值,或用于计算并返回字段值。例如:
C#
复制代码
class Employee
{
    private string name;
    public string Name
    {
        get
        {
            return name != null ? name : "NA" ;
        }
    }
}
在上述代码段中,如果不对 Name 属性赋值,它将返回值 NA。
 set 访问器
C#
复制代码
class Person
{
    private string name;  // the name field
    public string Name    // the Name property
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
}
当对属性赋值时,用提供新值的参数调用 set 访问器。例如:
C#
复制代码
Person p1 = new Person();
p1.Name = "Joe" // the set accessor is invoked here               
 
System.Console.Write(p1.Name);  // the get accessor is invoked here
set 访问器中,对局部变量声明使用隐式参数名称 value 是错误的。
 备注
可将属性标记为 publicprivateprotectedinternalprotected internal。这些访问修饰符定义类的用户如何才能访问属性。同一属性的 getset 访问器可能具有不同的访问修饰符。例如, get 可能是 public 以允许来自类型外的只读访问; set 可能是 privateprotected。有关更多信息,请参见 访问修饰符(C# 编程指南)
可以使用 static 关键字将属性声明为静态属性。这使得调用方随时可使用该属性,即使不存在类的实例。有关更多信息,请参见 静态类和静态类成员(C# 编程指南)

注意

 示例 1
此例说明了实例、静态和只读属性。它从键盘接受雇员的姓名,按 1 递增 NumberOfEmployees,并显示雇员的姓名和编号。
C#
复制代码
public class Employee
{
    public static int NumberOfEmployees;
    private static int counter;
    private string name;
 
    // A read-write instance property:
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
 
    // A read-only static property:
    public static int Counter
    {
        get { return counter; }
    }
 
    // A Constructor:
    public Employee()
    {
        // Calculate the employee's number:
        counter = ++counter + NumberOfEmployees;
    }
}
 
class TestEmployee
{
    static void Main()
    {
        Employee.NumberOfEmployees = 100;
        Employee e1 = new Employee();
        e1.Name = "Claude Vige" ;
 
        System.Console.WriteLine( "Employee number: {0}" , Employee.Counter);
        System.Console.WriteLine( "Employee name: {0}" , e1.Name);
    }
}
 输出 1
Employee number: 101
Employee name: Claude Vige
 示例 2
此例说明如何访问基类中被派生类中具有同一名称的另一个属性隐藏的属性。
C#
复制代码
public class Employee
{
    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}
 
public class Manager : Employee
{
    private string name;
 
    // Notice the use of the new modifier:
    public new string Name
    {
        get { return name; }
        set { name = value + ", Manager" ; }
    }
}
 
class TestHiding
{
    static void Main()
    {
        Manager m1 = new Manager();
 
        // Derived class property.
        m1.Name = "John" ;
 
        // Base class property.
        ((Employee)m1).Name = "Mary" ;
 
        System.Console.WriteLine( "Name in the derived class is: {0}" , m1.Name);
        System.Console.WriteLine( "Name in the base class is: {0}" , ((Employee)m1).Name);
    }
}
 输出 2
Name in the derived class is: John, Manager
Name in the base class is: Mary
 代码讨论
以下是上述示例中的要点:
派生类中的属性 Name 隐藏基类中的属性 Name。在这种情况下,派生类的属性声明中使用 new 修饰符:
C#
复制代码
public new string Name
转换 (Employee) 用于访问基类中的隐藏属性:
C#
复制代码
((Employee)m1).Name = "Mary" ;
有关隐藏成员的更多信息,请参见 new 修饰符(C# 参考)
 示例 3
在此例中, CubeSquare 这两个类实现抽象类 Shape,并重写它的抽象 Area 属性。注意属性上 override修饰符的使用。程序接受输入的边长并计算正方形和立方体的面积。它还接受输入的面积并计算正方形和立方体的相应边长。
C#
复制代码
abstract class Shape
{
    public abstract double Area
    {
        get ;
        set ;
    }
}
 
class Square : Shape
{
    public double side;
 
    public Square(double s)  //constructor
    {
        side = s;
    }
 
    public override double Area
    {
        get
        {
            return side * side;
        }
        set
        {
            side = System.Math.Sqrt(value);
        }
    }
}
 
class Cube : Shape
{
    public double side;
 
    public Cube(double s)
    {
       side = s;
    }
 
    public override double Area
    {
        get
        {
            return 6 * side * side;
        }
        set
        {
            side = System.Math.Sqrt(value / 6);
        }
    }
}
 
class TestShapes
{
    static void Main()
    {
        // Input the side:
        System.Console.Write( "Enter the side: " );
        double side = double.Parse(System.Console.ReadLine());
 
        // Compute the areas:
        Square s = new Square(side);
        Cube c = new Cube(side);
 
        // Display the results:
        System.Console.WriteLine( "Area of the square = {0:F2}" , s.Area);
        System.Console.WriteLine( "Area of the cube = {0:F2}" , c.Area);
        System.Console.WriteLine();
 
        // Input the area:
        System.Console.Write( "Enter the area: " );
        double area = double.Parse(System.Console.ReadLine());
 
        // Compute the sides:
        s.Area = area;
        c.Area = area;
 
        // Display the results:
        System.Console.WriteLine( "Side of the square = {0:F2}" , s.side);
        System.Console.WriteLine( "Side of the cube = {0:F2}" , c.side);
    }
}
输入
4
24
 输出 3
Enter the side: 4
Area of the square = 16.00
Area of the cube = 96.00
Enter the area: 24
Side of the square = 4.90
Side of the cube = 2.00
  (来源:msdn )
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值