【问题标题】:Implement Interface vs Implement Interface Explicitly in C# [duplicate]在 C# 中实现接口与显式实现接口 [重复]
【发布时间】:2012-03-01 00:29:34
【问题描述】:

我在 VS2010 中有两个选项来实现接口。

当我有 IHelper.cs 界面如下:

public interface IHelper
    ....
    IEnumerable<IPort> Ports { get; }

“显式实现接口”给出以下代码:

    IEnumerable<IPort> IHelper.Ports
    {
        get
        {
            ...
        }
    }

而且,“实现接口”给了我这个代码:

    public IEnumerable<IPort> Ports
    {
        get
        {
            ...
        }
    }

它们是相同的还是不同的?为什么在 C# 中实现接口时有两种选择?

【问题讨论】:

  • 会不会“实现公共接口”和“实现私有接口”太难了?

标签: c# visual-studio visual-studio-2010 interface


【解决方案1】:

显式接口声明意味着接口成员在接口本身以外的类型上不可用,因此在公开访问它们之前需要将实现类型转换为接口。

隐式是实现大多数接口的标准方式,它在实现者类型的公共 API 上公开接口项。

显式接口定义的主要原因是为了避免命名冲突,如果您碰巧实现了两个包含具有相同签名的方法的接口...显式定义允许编译器保持签名不同足以解决。

支持代码维护的第二个原因是,如 cmets 中的 XenoPuTtSs 所建议的那样,如果删除方法签名,显式定义将触发实现类型上的编译器错误。在隐式实现中,从接口中删除方法将使该方法成为任何类型的常规成员 - 这意味着您需要手动搜索现已失效的方法实现。

【讨论】:

  • 也(这不是主要原因)当接口发生变化(如方法被删除或更改)时,编译器将在显式定义接口的类上抛出错误,因为这些方法不再存在界面。这是从大型项目中查找未使用代码的有用方法(恕我直言)。
  • @XenoPuTtSs 好点,我已经修改了我的答案以包含这个。
【解决方案2】:

它们完全不同。如果您显式地实现接口,您将只能通过引用该接口来引用接口成员。下面的代码演示了这个想法。

public interface IFoo {
    String Bar { get; set; }
}
public class ImplicitFoo : IFoo {
    public string Bar {get;set;}
}
public class ExplicitFoo : IFoo {
    private String _Bar;
    string IFoo.Bar {
        get {
            return _Bar;
        }
        set {
            _Bar = value;
        }
    }
}
public class Test {
    public void Test() {
        var iml = new ImplicitFoo();
        // Works fine
        Console.WriteLine(iml.Bar);
        var expl = new ExplicitFoo();
        var fooInterface = (IFoo)expl;
        // Works fine
        Console.WriteLine(fooInterface.Bar);
        // Throws compile time exception
        Console.WriteLine(expl.Bar);
    }
}

【讨论】:

    【解决方案3】:

    实现接口的类可以显式实现该接口的成员。当显式实现成员时,不能通过类实例访问它,而只能通过接口的实例访问。

    // explicit1.cs
    interface IDimensions 
    {
      float Length();
      float Width();
    }
    
    class Box : IDimensions 
    {
      float lengthInches;
      float widthInches;
    
     public Box(float length, float width) 
     {
        lengthInches = length;
       widthInches = width;
     }
     // Explicit interface member implementation: 
     float IDimensions.Length() 
     {
        return lengthInches;
     }
     // Explicit interface member implementation:
     float IDimensions.Width() 
     {
        return widthInches;      
     }
    
     public static void Main() 
     {
       // Declare a class instance "myBox":
       Box myBox = new Box(30.0f, 20.0f);
      // Declare an interface instance "myDimensions":
      IDimensions myDimensions = (IDimensions) myBox;
      // Print out the dimensions of the box:
      /* The following commented lines would produce compilation 
         errors because they try to access an explicitly implemented
         interface member from a class instance:                   */
      //System.Console.WriteLine("Length: {0}", myBox.Length());
      //System.Console.WriteLine("Width: {0}", myBox.Width());
      /* Print out the dimensions of the box by calling the methods 
         from an instance of the interface:                         */
      System.Console.WriteLine("Length: {0}", myDimensions.Length());
      System.Console.WriteLine("Width: {0}", myDimensions.Width());
     }
    }
    

    显式接口实现还允许程序员继承两个共享相同成员名称的接口,并给每个接口成员一个单独的实现。此示例以公制和英制单位显示盒子的尺寸。 Box 类继承了两个接口 IEnglishDimensions 和 IMetricDimensions,分别代表不同的测量系统。两个接口具有相同的成员名称,长度和宽度。

    看例子

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

    更多详情请看article

    【讨论】:

    • 最好将文章中的相关信息包含在答案本身中,链接变化无常,可能不会与答案一样长。如果该链接失败,您的回答将无济于事。
    猜你喜欢
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    相关资源
    最近更新 更多