为什么明确实现接口?

Mas*_*ity 118 c# interface

那么,明确实现接口的一个好用例究竟是什么?

是否仅仅是因为使用该类的人不必在intellisense中查看所有这些方法/属性?

Iai*_*ain 141

如果实现两个具有相同方法和不同实现的接口,则必须明确实现.

public interface IDoItFast
{
    void Go();
}
public interface IDoItSlow
{
    void Go();
}
public class JustDoIt : IDoItFast, IDoItSlow
{
    void IDoItFast.Go()
    {
    }

    void IDoItSlow.Go()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的例子.喜欢界面/类名!:-) (10认同)
  • 我不喜欢它,在类中使用相同签名的两种方法可以做很多不同的事情吗?这是非常危险的东西,很可能会在任何大型开发中造成严重破坏.如果你有这样的代码,我会说你的分析和设计是起作用的. (10认同)
  • @Mike接口可能属于某个API或两个不同的API.也许*love*在这里有点夸张但我至少很高兴明确的实施可用. (4认同)

Mic*_*l B 63

隐藏非首选成员很有用.例如,如果你同时实现这两者IComparable<T>,IComparable那么隐藏IComparable重载通常会更好,不会让人觉得你可以比较不同类型的对象.同样,某些接口不符合CLS IConvertible,因此,如果您没有明确实现该接口,那么需要符合CLS的语言的最终用户将无法使用您的对象.(如果BCL实施者没有隐藏基元的IConvertible成员,那将是非常灾难性的:))

另一个有趣的注意事项是,通常使用这样的构造意味着显式实现接口的struct只能通过装箱到接口类型来调用它们.你可以通过使用泛型约束来解决这个问题::

void SomeMethod<T>(T obj) where T:IConvertible
Run Code Online (Sandbox Code Playgroud)

当你将一个int传递给它时,不会对它进行封装.


Wie*_*sma 36

明确实现接口的其他一些原因:

向后兼容性:如果ICloneable接口更改,实现方法类成员不必更改其方法签名.

更清洁的代码:如果Clone从IClo​​neable中删除该方法,将会出现编译器错误,但是如果您隐式实现该方法,则最终可能会使用未使用的"孤立"公共方法

强类型:为了用一个例子来说明supercat的故事,这将是我首选的示例代码,当您直接将其作为实例成员调用时,ICloneable显式实现允许Clone()强类型MyObject:

public class MyObject : ICloneable
{
  public MyObject Clone()
  {
    // my cloning logic;  
  }

  object ICloneable.Clone()
  {
    return this.Clone();
  }
}
Run Code Online (Sandbox Code Playgroud)


sup*_*cat 12

另一个有用的技术是让函数的方法的公共实现返回一个比接口中指定的更具体的值.

例如,一个对象可以实现ICloneable,但仍然有其公开可见的Clone方法返回其自己的类型.

同样,一个IAutomobileFactory可能有一个Manufacture方法返回一个Automobile,但是一个FordExplorerFactory实现IAutomobileFactoryManufacture方法可能让它的方法返回一个FordExplorer(派生自的Automobile).知道它有一个FordExplorerFactory可以FordExplorer在一个对象返回的对象上使用特定属性FordExplorerFactory而不必进行类型转换的代码,而只知道它有某种类型的代码只会IAutomobileFactory将其返回作为一个Automobile.

  • 在阅读这个答案时,有2个人会失明. (3认同)
  • +1 ...这将是我对显式接口实现的首选用法,尽管一个小代码示例可能比这个故事更清晰:) (2认同)

vcs*_*nes 7

当你有两个具有相同成员名称和签名的接口时,它也很有用,但是想根据它的使用方式改变它的行为.(我不建议像这样编写代码):

interface Cat
{
    string Name {get;}
}

interface Dog
{
    string Name{get;}
}

public class Animal : Cat, Dog
{
    string Cat.Name
    {
        get
        {
            return "Cat";
        }
    }

    string Dog.Name
    {
        get
        {
            return "Dog";
        }
    }
}
static void Main(string[] args)
{
    Animal animal = new Animal();
    Cat cat = animal; //Note the use of the same instance of Animal. All we are doing is picking which interface implementation we want to use.
    Dog dog = animal;
    Console.WriteLine(cat.Name); //Prints Cat
    Console.WriteLine(dog.Name); //Prints Dog
}
Run Code Online (Sandbox Code Playgroud)

  • 我见过的最奇怪的OO相关例子:`public class Animal:Cat,Dog` (59认同)
  • @mbx:如果Animal也实施了鹦鹉,它将是一只波莉变形动物. (38认同)
  • 我记得一个卡通人物,一端是猫,另一端是狗;-) (3认同)
  • 在80年代有一部电视剧......"Manimal"......一个男人可以变身为......哦,没关系 (2认同)

Mik*_*our 5

如果您有一个内部接口,并且您不希望公开地在您的类上实现成员,那么您将明确地实现它们.隐式实现必须是公开的.


Bro*_*ass 5

它可以使公共接口更清晰,以显式实现接口,即您的File类可以IDisposable显式实现并提供一个公共方法Close(),这可能对消费者更有意义Dispose(.

F#提供显式接口实现,因此您必须始终转换为特定接口以访问其功能,这使得接口的使用非常明确(无双关语).

  • 我不喜欢你的特定例子(恕我直言,唯一应该隐藏`Dispose`的东西是那些永远不需要清理的东西); 一个更好的例子就像一个不可变集合的`IList <T> .Add`的实现. (2认同)

h b*_*bob 5

显式实现的另一个原因是可维护性

当一个类变得“忙碌”时——是的,它发生了,我们并不都有重构其他团队成员的代码的奢侈——然后有一个明确的实现可以清楚地表明一个方法在那里满足接口契约。

所以它提高了代码的“可读性”。