Explain the interface attributes in C and the access restrictions of attribute accessors in detail

  • 2021-09-05 00:40:29
  • OfStack

Interface attributes
You can declare properties on interfaces. The following is an example of an interface indexer accessor:


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

The accessor of an interface property does not have a body. Therefore, the purpose of the accessor is to indicate whether the property is read-write, read-only, or write-only.
In this example, the interface IEmployee has a read-write attribute Name and a read-only attribute Counter. The Employee class implements the IEmployee interface and uses both properties. The program reads the name of the new employee and the employee's current number, and displays the employee's name and calculated employee number.
You can use the fully qualified name of the property, which references the interface where the member is declared. For example:


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

This is called explicit interface implementation (C # programming guide). For example, if the Employee class implements two interfaces, ICitizen and IEmployee, and both interfaces have the Name attribute, an explicit interface member implementation is required. That is, the following attribute declaration:


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

The Name property is implemented on the IEmployee interface, and the following declaration:


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

Implement the Name property on the ICitizen interface.


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

For example, here we enter:


210
Hazem Abolrous

The sample output


Enter number of employees: 210
Enter the name of the new employee: Hazem Abolrous
The employee information:
Employee number: 211
Employee name: Hazem Abolrous

Limit accessibility of accessors
The get and set parts of a property or indexer are called "accessors". By default, these accessors have the same visibility or access level: the visibility or access level of the property or indexer to which they belong. However, it is sometimes useful to restrict access to one of these accessors. The accessibility of the set accessor is usually limited while maintaining the public access of the get accessor. For example:


private string name = "Hello";

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

In this example, the property named Name defines one get accessor and one set accessor. The get accessor accepts the accessibility level of the attribute itself (public in this example), while for the set accessor, it is explicitly restricted by applying an protected access modifier to the accessor itself.
Restrictions on access modifiers of accessors
Using access modifiers on properties or indexers is subject to the following conditions:
You cannot use accessor modifiers on interfaces or explicit interface member implementations.
Accessor modifiers can only be used if a property or indexer has both set and get accessors. In this case, modifiers are allowed on only one of the accessors.
If the property or indexer has an override modifier, the accessor modifier must match the accessor, if any, of the overridden accessor.
The accessibility level of the accessor must be more restrictive than the accessibility level of the property or indexer itself.
Override the access modifier of the accessor
When you override a property or indexer, the accessor being overridden must be accessible to the overridden code. In addition, the accessibility levels of both the property/indexer and accessor must match the corresponding overridden property/indexer and accessor. For example:


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

Implementation interface
When using an accessor to implement an interface, the accessor cannot have an access modifier. However, if you implement the interface with one accessor, such as get, the other accessor can have access modifiers, as shown in the following example:


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 { }
  }
}

Accessibility domain of accessor
If an access modifier is used on an accessor, the accessibility domain of the accessor is determined by that modifier.
If access modifiers are not used for an accessor, the accessibility domain of the accessor is determined by the accessibility level of the property or indexer.
The following example contains three classes: BaseClass, DerivedClass, and MainClass. BaseClass, Name, and Id of each class have two attributes. This example demonstrates how to hide the Id property of DerivedClass through the Id property of BaseClass when using restricted access modifiers such as protected or private. Therefore, when you assign a value to this property, the property in the BaseClass class is called. Replacing the access modifier with public will make the property accessible.
The example also demonstrates how restricted access modifiers on the set accessor of the Name property of DerivedClass, such as private or protected, prevent access to the accessor and generate errors when assigning values to it.


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

Output:


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


Related articles: