简体   繁体   English

为什么显式接口实现?

[英]Why explicit interface implementation?

I recently implemented a class like: 我最近实现了一个类:

class TestClass : IDisposable
{
    RegistryKey m_key;
    public TestClass()
    {
        m_key = Registry.CurrentUser.OpenSubKey("Software", false);
    }

    public void Dispose()
    {
        // m_key.Dispose();
        IDisposable disp = m_key;
        disp.Dispose();
    }
}

If I uncomment the direct call to Dispose, I get error CS0117 ("'Microsoft.Win32.RegistryKey' does not contain a definition for 'Dispose'"). 如果我取消注释直接调用Dispose,我会收到错误CS0117(“'Microsoft.Win32.RegistryKey'不包含'Dispose'的定义”)。 Some Googling led me to this thread , where I learned what was going on, so I now understand the mechanics of it. 一些谷歌搜索引导我到这个线程 ,在那里我了解了发生了什么,所以我现在了解它的机制。 The MSDN documentation suggests that the author would prefer that I call Close() instead of Dispose(), but doesn't explain why. MSDN文档表明作者更喜欢我调用Close()而不是Dispose(),但不解释原因。

What is the purpose of this pattern (which I think I've seen it in the IO classes as well)? 这种模式的目的是什么(我认为我在IO类中也看到了它)? In light of the fact that this was an intentional decision by the class author, how bad is the code above (the call to Dispose through the IDisposable interface)? 鉴于这是班级作者的故意决定,上面的代码有多糟糕(通过IDisposable接口调用Dispose)? It can't be too bad - after all, it's what would happen in a using statement, right? 它不会太糟糕 - 毕竟,这是在使用声明中会发生什么,对吧?

[edits: 1) changed title from "non-public" to "explicit" 2) removed the explicit implementation from my code, accidentally left in from experimentation] [编辑:1]将标题从“非公开”更改为“显式”2)从我的代码中删除了显式实现,意外地从实验中留下了]

This is called explicit interface implementation . 这称为显式接口实现 In your example since you define the Dispose() method as "void IDisposable.Dispose()" you are explicitly implementing the IDisposable interface as well. 在您的示例中,因为您将Dispose()方法定义为“void IDisposable.Dispose()”,所以您也明确地实现了IDisposable接口。

This is normally done to avoid collisions. 通常这样做是为了避免碰撞。 If Microsoft ever wanted to add another Dispose() method that did something else to RegistryKey they wouldn't be able to unless they used explicit implementation of that interface. 如果Microsoft想要添加另一个为RegistryKey做其他事情的Dispose()方法,除非他们使用该接口的显式实现,否则他们将无法做到。

This is done often with the generic IEnumerable<T> interface. 这通常使用通用的IEnumerable <T>接口来完成。 It requires you to also implement the non-generic interface IEnumerable. 它还要求您还实现非通用接口IEnumerable。 The only member in these two interfaces is GetEnumerator, with the generic one being more useful, so its usually implemented like this: 这两个接口中唯一的成员是GetEnumerator,通用的一个更有用,所以它通常像这样实现:

public clas SomeClass : IEnumerable<SomeOtherClass>
{
    public IEnumerator<SomeOtherClass> GetEnumerator ()
    {
        ...
    }

    IEnumerator IEnumerable.GetEnumerator ()
    {
        return GetEnumerator ();
    }
}

This way when you call an object of SomeClass's GetEnumator method, it calls the generic version, since the other one was implemented explicitly, allowing us to get the strong-typing generics allow. 这样当你调用SomeClass的GetEnumator方法的对象时,它会调用泛型版本,因为另一个是明确实现的,这使得我们可以获得强类型泛型。

See pages 166-169 of Programming C# by Jesse Liberty (I've got the fourth edition). 参见Jesse Liberty 编程C#的第166-169页(我已经获得了第四版)。

Most people don't agree with me, but I like using explicit interface implementation for all interfaces . 大多数人不同意我的意见,但我喜欢对所有接口使用显式接口实现 I want to make it clear whether I'm writing a method to be called on my object or on my interface. 我想说清楚我是在写一个方法来调用我的对象还是我的界面。

This is painful if you have a reference to the object and want to call an interface method (like the above example), but I mitigate it by writing: 如果你有一个对象的引用并想要调用一个接口方法(如上面的例子),这很痛苦,但我通过编写来缓解它:

class C : IDisposable
{
    public IDisposable IDisposable { get { return this; } }
    void IDisposable.Dispose() { }
}

which means that calling the method on C looks like: 这意味着在C上调用方法看起来像:

C c = ...
c.IDisposable.Dispose();

The compiler parses this as "Call the IDisposable property on C, then call the Dispose() method on the result" but I read it as "Call the IDisposable.Dispose() method on C " which seems natural here. 编译器将其解析为“在C上调用IDisposable属性,然后在结果上调用Dispose()方法”但我将其读作“在C上调用IDisposable.Dispose()方法”,这在这里看起来很自然。

This approach can get ugly when using generic interfaces, unfortunately. 遗憾的是,这种方法在使用通用接口时会变得很难看。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM