如何在c#中定义接口的默认实现?

时间:2010-07-17 11:09:43

标签: .net inheritance interface

c#中有一些黑魔法代码,您可以在其中定义接口的默认实现。

所以你可以写

var instance = new ISomeInterface();

任何指针?

更新1:请注意,我没有问这是不是一个好主意。怎么可能这样做。

更新2:任何人都能看到接受的答案。

  • “这应该仅仅被视为一种好奇心。”来自Marc Gravel "Newing up" Interfaces
  • “使用专为COM互操作设计的工具来做一些完全不同的事情是个坏主意。这使得下一个必须维护它的人无法理解你的代码”来自Eric Lippert "Newing up" Interfaces < / LI>
  • “虽然它可能有用,但如果它是由理性编码器在生产代码中找到的,那么它将被重构为使用基类或依赖注入。”来自Stephen Cleary的评论如下。

3 个答案:

答案 0 :(得分:32)

黑魔法来了:

class Program
{
    static void Main()
    {
        IFoo foo = new IFoo("black magic");
        foo.Bar();
    }
}

[ComImport]
[Guid("C8AEBD72-8CAF-43B0-8507-FAB55C937E8A")]
[CoClass(typeof(FooImpl))]
public interface IFoo
{
    void Bar();
}

public class FooImpl : IFoo
{
    private readonly string _text;
    public FooImpl(string text)
    {
        _text = text;
    }

    public void Bar()
    {
        Console.WriteLine(_text);
    }
}

请注意,您不仅可以实例化接口,还可以将参数传递给其构造函数: - )

答案 1 :(得分:3)

仅当ISomeInterface是一个类时。

更新(澄清):

Jon Skeet有a talk,他提到了接口的默认实现。但它们不是C#语言的一部分。这个谈论是关于Jon Skeet将会在未来的C#版本中看到 的内容。

目前,唯一的默认实现是通过(可能是abstract)基类完成的。

答案 2 :(得分:2)

也许您参考依赖注入?在使用DI框架(例如Ninject或Unity)时,您可以为每个接口定义默认实例,然后像这样使用它:

(假设你有IWeapon接口而Sword实现了它)

IKernel kernel = new StandardKernel();
kernel.Bind<IWeapon>().To<Sword>();
var weapon = kernel.Get<IWeapon>();

但是Ninject(以及大多数其他IoC框架)可以做一些更聪明的事情,例如:假设我们有一个类Warrior,它将IWeapon作为其构造函数中的参数。我们可以从Ninject获取Warrior的实例:

var warrior = kernel.Get<Warrior>();

Ninject会将我们指定的IWeapon实现传递给Warrior构造函数方法并返回新实例。

除此之外,我不知道任何允许这种行为的语言功能。