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

 更新时间:2020年6月25日 11:25  点击:2236

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

public interface ISampleInterface
{
  // Property declaration:
  string Name
  {
    get;
    set;
  }
}

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

string IEmployee.Name
{
  get { return "Employee Name"; }
  set { }
}

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

string IEmployee.Name
{
  get { return "Employee Name"; }
  set { }
}

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

string ICitizen.Name
{
  get { return "Citizen Name"; }
  set { }
}

在 ICitizen 接口上实现 Name 属性。

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);
  }
}

比如这里我们输入:

210
Hazem Abolrous

则示例输出

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 访问器的可访问性。例如:

private string name = "Hello";

public string Name
{
  get
  {
    return name;
  }
  protected set
  {
    name = value;
  }
}

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

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)实现接口,则另一个访问器可以具有访问修饰符,如下面的示例所示:

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)如何防止对该访问器的访问,并在向它赋值时生成错误。

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();
  }
}

输出:

  Base: Name-BaseClass, ID-BaseClass
  Derived: John, ID-BaseClass

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25