服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 详解C#中的属性和属性的使用

详解C#中的属性和属性的使用

2021-11-09 13:01C#教程网 C#

这篇文章主要介绍了C#中的属性和属性的使用,包括get访问器和set访问器等内容,需要的朋友可以参考下

属性
属性是一种成员,它提供灵活的机制来读取、写入或计算私有字段的值。属性可用作公共数据成员,但它们实际上是称为“访问器”的特殊方法。这使得可以轻松访问数据,还有助于提高方法的安全性和灵活性。
在此示例中,TimePeriod 类存储时间段。该类在内部以秒为单位存储时间,但是名为 Hours 的属性允许客户端以小时为单位指定时间。 Hours 属性的访问器执行小时与秒之间的转换。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class TimePeriod
{
  private double seconds;
 
  public double Hours
  {
    get { return seconds / 3600; }
    set { seconds = value * 3600; }
  }
}
 
 
class Program
{
  static void Main()
  {
    TimePeriod t = new TimePeriod();
 
    // Assigning the Hours property causes the 'set' accessor to be called.
    t.Hours = 24;
 
    // Evaluating the Hours property causes the 'get' accessor to be called.
    System.Console.WriteLine("Time in hours: " + t.Hours);
  }
}

输出:

?
1
Time in hours: 24

表达式主体定义
直接只返回表达式结果的属性很常见。下面的语法快捷方式使用 => 来定义这些属性:

?
1
public string Name => First + " " + Last;

属性必须为只读,并且你不能使用 get 访问器关键字。

使用属性
属性结合了字段和方法的多个方面。对于对象的用户,属性显示为字段,访问该属性需要相同的语法。对于类的实现者,属性是一个或两个代码块,表示一个 get 访问器和/或一个 set 访问器。当读取属性时,执行 get 访问器的代码块;当向属性分配一个新值时,执行 set 访问器的代码块。不具有 set 访问器的属性被视为只读属性。不具有 get 访问器的属性被视为只写属性。同时具有这两个访问器的属性是读写属性。

属性具有多种用法:它们可在允许更改前验证数据;它们可透明地公开某个类上的数据,该类的数据实际上是从其他源(例如数据库)检索到的;当数据被更改时,它们可采取行动,例如引发事件或更改其他字段的值。
属性在类块中是按以下方式来声明的:指定字段的访问级别,接下来指定属性的类型和名称,然后跟上声明 get 访问器和/或 set 访问器的代码块。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 属性使用私有字段来跟踪该实际值。属性的数据的真实位置经常称为属性的“后备存储”。属性使用作为后备存储的私有字段是很常见的。将字段标记为私有可确保该字段只能通过调用属性来更改。


get 访问器
get 访问器体与方法体相似。它必须返回属性类型的值。执行 get 访问器相当于读取字段的值。例如,当正在从 get 访问器返回私有变量并且启用了优化时,对 get 访问器方法的调用由编译器进行内联,因此不存在方法调用的系统开销。然而,由于在编译时编译器不知道在运行时实际调用哪个方法,因此无法内联虚拟 get 访问器。以下是返回私有字段 name 的值的 get 访问器:

?
1
2
3
4
5
6
7
8
9
10
11
class Person
{
  private string name; // the name field
  public string Name  // the Name property
  {
    get
    {
      return name;
    }
  }
}

当引用属性时,除非该属性为赋值目标,否则将调用 get 访问器以读取该属性的值。例如:

?
1
2
3
4
Person person = new Person();
//...
 
System.Console.Write(person.Name); // the get accessor is invoked here

get 访问器必须以 return 或 throw 语句终止,并且控制权不能离开访问器体。
通过使用 get 访问器更改对象的状态不是一种好的编程风格。例如,以下访问器在每次访问 number 字段时都会产生更改对象状态的副作用。

?
1
2
3
4
5
6
7
8
private int number;
public int Number
{
  get
  {
    return number++;  // Don't do this
  }
}

get 访问器可用于返回字段值,或用于计算并返回字段值。例如:

?
1
2
3
4
5
6
7
8
9
10
11
class Employee
{
  private string name;
  public string Name
  {
    get
    {
      return name != null ? name : "NA";
    }
  }
}

在上一个代码段中,如果不对 Name 属性赋值,它将返回值 NA。
set 访问器
set 访问器类似于返回类型为 void 的方法。它使用称为 value 的隐式参数,此参数的类型是属性的类型。在下面的示例中,将 set 访问器添加到 Name 属性:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person
{
  private string name; // the name field
  public string Name  // the Name property
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  }
}

当对属性赋值时,用提供新值的参数调用 set 访问器。例如:

?
1
2
3
4
Person person = new Person();
person.Name = "Joe"; // the set accessor is invoked here       
 
System.Console.Write(person.Name); // the get accessor is invoked here

在 set 访问器中,对局部变量声明使用隐式参数名称 value 是错误的。

此例说明了实例、静态和只读属性。它从键盘接受雇员的姓名,按 1 递增 NumberOfEmployees,并显示雇员的姓名和编号。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 = 107;
    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
2
Employee number: 108
Employee name: Claude Vige

此示例说明如何访问基类中由派生类中具有同一名称的另一个属性所隐藏的属性。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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);
  }
}

输出:

?
1
2
Name in the derived class is: John, Manager
Name in the base class is: Mary

以下是上一个示例中的要点:
派生类中的属性 Name 隐藏基类中的属性 Name。在这种情况下,派生类的属性声明中使用 new 修饰符:

?
1
public new string Name

转换 (Employee) 用于访问基类中的隐藏属性:

?
1
((Employee)m1).Name = "Mary";

在此例中,Cube 和 Square 这两个类实现抽象类 Shape,并重写它的抽象 Area 属性。注意属性上 override 修饰符的使用。程序接受输入的边长并计算正方形和立方体的面积。它还接受输入的面积并计算正方形和立方体的相应边长。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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);
  }
}

输出:

?
1
2
3
4
5
6
7
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

 

延伸 · 阅读

精彩推荐
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16