C#中显式接口的使用

本文关键字:接口 | 更新日期: 2023-09-27 17:58:35

我可以使用显式接口将方法隐藏在实现类中,如下所示:

interface IInterface
{
    void f1();
}
public class C1 : IInterface
{
    void IInterface.f1()
    {
        Console.WriteLine(" Method Called ....");
    }
}

然后可以访问方法:

C1 C = new C1();
IInterface i = C;
i.f1();

方法f1将对实现类C1隐藏。这种功能的目的是什么?有人能为我提供一个我们需要的真实生活场景吗?

C#中显式接口的使用

这里有一个MSDN的好例子,它帮助我理解了为什么它们会有所帮助:

此示例以公制和英制单位显示长方体的尺寸。Box类继承了两个接口IEnglishDimensions和IMetricDimensions,这两个接口表示不同的测量系统。两个接口都具有相同的成员名称Length和Width。

// explicit2.cs
// Declare the English units interface:
interface IEnglishDimensions 
{
   float Length();
   float Width();
}
// Declare the metric units interface:
interface IMetricDimensions 
{
   float Length();
   float Width();
}
// Declare the "Box" class that implements the two interfaces:
// IEnglishDimensions and IMetricDimensions:
class Box : IEnglishDimensions, IMetricDimensions 
{
   float lengthInches;
   float widthInches;
   public Box(float length, float width) 
   {
      lengthInches = length;
      widthInches = width;
   }
// Explicitly implement the members of IEnglishDimensions:
   float IEnglishDimensions.Length() 
   {
      return lengthInches;
   }
   float IEnglishDimensions.Width() 
   {
      return widthInches;      
   }
// Explicitly implement the members of IMetricDimensions:
   float IMetricDimensions.Length() 
   {
      return lengthInches * 2.54f;
   }
   float IMetricDimensions.Width() 
   {
      return widthInches * 2.54f;
   }
   public static void Main() 
   {
      // Declare a class instance "myBox":
      Box myBox = new Box(30.0f, 20.0f);
      // Declare an instance of the English units interface:
      IEnglishDimensions eDimensions = (IEnglishDimensions) myBox;
      // Declare an instance of the metric units interface:
      IMetricDimensions mDimensions = (IMetricDimensions) myBox;
      // Print dimensions in English units:
      System.Console.WriteLine("Length(in): {0}", eDimensions.Length());
      System.Console.WriteLine("Width (in): {0}", eDimensions.Width());
      // Print dimensions in metric units:
      System.Console.WriteLine("Length(cm): {0}", mDimensions.Length());
      System.Console.WriteLine("Width (cm): {0}", mDimensions.Width());
   }
}

在某些情况下,您不想以直接的形式在公共API上公开某些内容。也许它永远不会起作用;也许公共API可以公开相同功能的更合适的签名。例如:

public int Add(Foo foo) {...} // takes a known type and returns the new index
void ICollection.Add(object obj) {...} // takes object and returns void

一个更常见的例子是,当不可能不这样做时——例如,IEnumerableIEnumerable<T>都有一个GetEnumerator()方法——输入相同,但返回值不同。C#不允许通过返回值重载,所以您至少需要两种方法:

IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<T> GetEnumerator() { ...}

尽管它们也可以都是明确的。或者实际上,在IEnumerator<T>:中

public T Current { get { ... } }
object IEnumerator.Current { get { return Current; } }

此外,有时您只是想重命名一些东西。例如,由于某种原因,Frobber具有一种自然是Frob()的方法。但它也实现了IDoSomething接口,该接口具有DoIt()方法;现在,您可以使API反映最合适的术语来表达意图:

class Frobber : IDoSomething {
  public void Frob() {..}
  void IDoSomething.DoIt() { Frob(); }
}

您可以在这里查看隐式和显式接口之间的区别:

C#接口。隐式实现与显式实现

真正的场景之一是方法名称冲突。想象一下:

interface IWarehouseItem
{
    string Name {get;} // the NAME of the PRODUCT
    int Count {get;}
    int PricePerUnit {get;}
}
interface IWarehouseSupplierInformation
{
    string Name {get;} // the NAME of the SUPPLIER
    int ID {get;}
    int IDAddress {get;}
}
class PurchaseableItem : Entity, IWarehouseItem, IWarehouseSupplierInformation
{
    ....
    // how to implement those different names?
     ....
    string IWarehouseItem.Name { get { this.Product.Name; } }
    ...
    string IWarehouseSupplierInformation.Name { get { this.Supplier.Name; } }
}

有人可能会说,这个例子只是接口和数据结构的糟糕设计,但你并不总是能够使它们正确,或者根本没有能力改变它们。

其他时候,您可能会被迫在类上实现一些接口,但您确实不希望这些方法对类的用户可见所有显式实现都被认为是私有的,因此,除非您显式地将对象强制转换回那个有问题的接口,否则没有人会看到或能够使用这些方法。