可以转换为未继承的接口吗?

Mat*_*mas 12 c#

为什么不能投射一个实例:

sealed class Foo
{
    public void Go() { }
}
Run Code Online (Sandbox Code Playgroud)

...到这个界面:

interface IBar
{
    void Go();
}
Run Code Online (Sandbox Code Playgroud)

......即使Foo有签名IBar

如何将实例Foo转换为IBar?假设我无法控制Foo.

Dai*_*Dai 25

不,C#不支持鸭子打字.

OOP解决此问题的方法是使用适配器模式.

你会这样做:

class FooBarAdapter : IBar {

    private readonly Foo foo;

    public FooBarAdapter(Foo foo) {

        this.foo = foo;
    }

    public void Go() {

        this.foo.Go();
    }
}
Run Code Online (Sandbox Code Playgroud)

每当你有一个Foo但需要IBar你按需包装时:

public void ContrivedScenario() {

    Foo foo = GetFooFromExternalDependency();

    FooBarAdapter adapter = new FooBarAdapter( foo );

    this.NeedsIBar( adapter );
}

public void NeedsIBar(IBar bar) { ... }
Run Code Online (Sandbox Code Playgroud)

我注意到,如果Foo至- IBar转换发生了很多,你可以使用隐式转换,所以你并不需要显式地构造FooBarAdapter的情况下,却是值得商榷的,如果这是良好的软件工程实践与否:

class FooBarAdapter : IBar {

    // (same as above)

    public static implicit operator FooBarAdapter(Foo foo) {
        return new FooBarAdapter( foo );
    }
}
Run Code Online (Sandbox Code Playgroud)

这样你可以这样做:

public void ContrivedScenario() {

    Foo foo = GetFooFromExternalDependency();

    this.NeedsIBar( foo ); // the conversion from `Foo foo` to `FooBarAdapter` happens implicitly
}
Run Code Online (Sandbox Code Playgroud)

C#不支持duck-typing的一个原因是因为类的接口(在OOP意义上,不是文字interface)与另一个共享相同的标识符,并不意味着它们是兼容的.例如Process.Kill(杀死过程)和MegaDeathKillBot3000.Kill(杀死所有人类)可能不应该互换使用......除非你真的想要.