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

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

服务器之家 - 编程语言 - C# - 详解C#中的接口属性以及属性访问器的访问限制

详解C#中的接口属性以及属性访问器的访问限制

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

这篇文章主要介绍了详解C#中的接口属性以及属性访问器的访问限制,文中讲到了使用访问器实现接口时添加访问修饰符的问题,需要的朋友可以参考下

接口属性
可以在接口上声明属性。以下是接口索引器访问器的示例:

?
1
2
3
4
5
6
7
8
9
public interface ISampleInterface
{
  // Property declaration:
  string Name
  {
    get;
    set;
  }
}

接口属性的访问器不具有体。因此,访问器的用途是指示属性是否为读写、只读或只写。
在此例中,接口 IEmployee 具有读写属性 Name 和只读属性 Counter。 Employee 类实现 IEmployee 接口并使用这两种属性。程序读取新雇员的姓名和雇员的当前编号,并显示雇员姓名和计算所得的雇员编号。
可以使用属性的完全限定名,它引用声明成员的接口。例如:

?
1
2
3
4
5
string IEmployee.Name
{
  get { return "Employee Name"; }
  set { }
}

这称为显式接口实现(C# 编程指南)。例如,如果 Employee 类实现两个接口 ICitizen 和 IEmployee,并且两个接口都具有 Name 属性,则需要显式接口成员实现。即,如下属性声明:

?
1
2
3
4
5
string IEmployee.Name
{
  get { return "Employee Name"; }
  set { }
}

在 IEmployee 接口上实现 Name 属性,而下面的声明:

?
1
2
3
4
5
string ICitizen.Name
{
  get { return "Citizen Name"; }
  set { }
}

在 ICitizen 接口上实现 Name 属性。

?
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
interface IEmployee
{
  string Name
  {
    get;
    set;
  }
 
  int Counter
  {
    get;
  }
}
 
public class Employee : IEmployee
{
  public static int numberOfEmployees;
 
  private string name;
  public string Name // read-write instance property
  {
    get
    {
      return name;
    }
    set
    {
      name = value;
    }
  }
 
  private int counter;
  public int Counter // read-only instance property
  {
    get
    {
      return counter;
    }
  }
 
  public Employee() // constructor
  {
    counter = ++counter + numberOfEmployees;
  }
}
 
class TestEmployee
{
  static void Main()
  {
    System.Console.Write("Enter number of employees: ");
    Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());
 
    Employee e1 = new Employee();
    System.Console.Write("Enter the name of the new employee: ");
    e1.Name = System.Console.ReadLine();
 
    System.Console.WriteLine("The employee information:");
    System.Console.WriteLine("Employee number: {0}", e1.Counter);
    System.Console.WriteLine("Employee name: {0}", e1.Name);
  }
}

比如这里我们输入:

?
1
2
210
Hazem Abolrous

则示例输出

?
1
2
3
4
5
Enter number of employees: 210
Enter the name of the new employee: Hazem Abolrous
The employee information:
Employee number: 211
Employee name: Hazem Abolrous

 

限制访问器可访问性
属性或索引器的 get 和 set 部分称为“访问器”。默认情况下,这些访问器具有相同的可见性或访问级别:其所属属性或索引器的可见性或访问级别。不过,有时限制对其中某个访问器的访问会很有用。通常是在保持 get 访问器可公开访问的情况下,限制 set 访问器的可访问性。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
private string name = "Hello";
 
public string Name
{
  get
  {
    return name;
  }
  protected set
  {
    name = value;
  }
}

在此示例中,名为 Name 的属性定义了一个 get 访问器和一个 set 访问器。 get 访问器接受该属性本身的可访问性级别(在此示例中为 public),而对于 set 访问器,则通过对该访问器本身应用 protected 访问修饰符来进行显式限制。
对访问器的访问修饰符的限制
对属性或索引器使用访问修饰符受以下条件的制约:
不能对接口或显式接口成员实现使用访问器修饰符。
仅当属性或索引器同时具有 set 和 get 访问器时,才能使用访问器修饰符。这种情况下,只允许对其中一个访问器使用修饰符。
如果属性或索引器具有 override 修饰符,则访问器修饰符必须与重写的访问器的访问器(如果有的话)匹配。
访问器的可访问性级别必须比属性或索引器本身的可访问性级别具有更严格的限制。
重写访问器的访问修饰符
在重写属性或索引器时,被重写的访问器对重写代码而言,必须是可访问的。此外,属性/索引器和访问器的可访问性级别都必须与相应的被重写属性/索引器和访问器匹配。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Parent
{
  public virtual int TestProperty
  {
    // Notice the accessor accessibility level.
    protected set { }
 
    // No access modifier is used here.
    get { return 0; }
  }
}
public class Kid : Parent
{
  public override int TestProperty
  {
    // Use the same accessibility level as in the overridden accessor.
    protected set { }
 
    // Cannot use access modifier here.
    get { return 0; }
  }
}

实现接口
使用访问器实现接口时,访问器不能具有访问修饰符。但是,如果使用一个访问器(如 get)实现接口,则另一个访问器可以具有访问修饰符,如下面的示例所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface ISomeInterface
{
  int TestProperty
  {
    // No access modifier allowed here
    // because this is an interface.
    get;
  }
}
 
public class TestClass : ISomeInterface
{
  public int TestProperty
  {
    // Cannot use access modifier here because
    // this is an interface implementation.
    get { return 10; }
 
    // Interface property does not have set accessor,
    // so access modifier is allowed.
    protected set { }
  }
}

访问器可访问性域
如果对访问器使用访问某个修饰符,则访问器的可访问性域由该修饰符确定。
如果不对访问器使用访问修饰符,则访问器的可访问性域由属性或索引器的可访问性级别确定。
下面的示例包含三个类:BaseClass、DerivedClass 和 MainClass。每个类的 BaseClass、Name 和 Id 都有两个属性。该示例演示在使用限制性访问修饰符(如 protected 或 private)时,如何通过 BaseClass 的 Id 属性隐藏 DerivedClass 的 Id 属性。因此,向该属性赋值时,将调用 BaseClass 类中的属性。将访问修饰符替换为 public 将使该属性可访问。
该示例还演示 DerivedClass 的 Name 属性的 set 访问器上的限制性访问修饰符(如 private 或 protected)如何防止对该访问器的访问,并在向它赋值时生成错误。

?
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
public class BaseClass
{
  private string name = "Name-BaseClass";
  private string id = "ID-BaseClass";
 
  public string Name
  {
    get { return name; }
    set { }
  }
 
  public string Id
  {
    get { return id; }
    set { }
  }
}
 
public class DerivedClass : BaseClass
{
  private string name = "Name-DerivedClass";
  private string id = "ID-DerivedClass";
 
  new public string Name
  {
    get
    {
      return name;
    }
 
    // Using "protected" would make the set accessor not accessible.
    set
    {
      name = value;
    }
  }
 
  // Using private on the following property hides it in the Main Class.
  // Any assignment to the property will use Id in BaseClass.
  new private string Id
  {
    get
    {
      return id;
    }
    set
    {
      id = value;
    }
  }
}
 
class MainClass
{
  static void Main()
  {
    BaseClass b1 = new BaseClass();
    DerivedClass d1 = new DerivedClass();
 
    b1.Name = "Mary";
    d1.Name = "John";
 
    b1.Id = "Mary123";
    d1.Id = "John123"; // The BaseClass.Id property is called.
 
    System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id);
    System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id);
 
    // Keep the console window open in debug mode.
    System.Console.WriteLine("Press any key to exit.");
    System.Console.ReadKey();
  }
}

输出:

?
1
2
Base: Name-BaseClass, ID-BaseClass
Derived: John, ID-BaseClass

延伸 · 阅读

精彩推荐
  • C#深入理解C#的数组

    深入理解C#的数组

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

    佳园9492021-12-10
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

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

    C#教程网11852021-11-16
  • C#三十分钟快速掌握C# 6.0知识点

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

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

    雨夜潇湘8272021-12-28
  • C#SQLite在C#中的安装与操作技巧

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

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

    蓝曈魅11162022-01-20
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

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

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

    bbird201811792022-03-05
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

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

    张信秀7712021-12-15
  • C#C#微信公众号与订阅号接口开发示例代码

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

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

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

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

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

    GhostRider10972022-01-21