Подтвердить что ты не робот

Как определить реализацию интерфейса по умолчанию в С#?

В С# есть код черной магии, где вы можете определить реализацию интерфейса по умолчанию.

Итак, вы можете написать

var instance = new ISomeInterface();

Любые указатели?

ОБНОВЛЕНИЕ 1: Обратите внимание, что это не спросит, является ли это хорошей идеей. Как это было возможно?

ОБНОВЛЕНИЕ 2: любому, кто видит принятый ответ.

  • "к этому нужно относиться просто как к любопытству". от Марка Гравеля "Новинг вверх" Интерфейсы
  • "Неплохая идея использовать инструмент, предназначенный для взаимодействия с COM, чтобы сделать что-то совершенно и совершенно другое. Это делает ваш код невозможным для понимания для следующего парня, который должен его поддерживать" от Eric Lippert "Newing up" Интерфейсы
  • "Хотя это может сработать, если оно было когда-либо обнаружено в производственном коде с помощью рационального кодера, вместо этого было бы реорганизовано использование базового класса или инъекции зависимостей". от Стивена Клири в комментарии ниже.
4b9b3361

Ответ 1

Вот черная магия:

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

Обратите внимание, что вы можете не только создать экземпляр интерфейса, но также передать аргументы его конструктору: -)

Ответ 2

Только если ISomeInterface является классом.

Обновление (для уточнения):

Jon Skeet беседа, где он упоминает реализации по умолчанию для интерфейсов. Однако они не являются частью языка С#. Разговор о том, что Джон Скит хотел бы увидеть в будущей версии С#.

В настоящее время единственные реализации по умолчанию выполняются через (возможно, abstract) базовые классы.

Ответ 3

Может быть, вы ссылаетесь на Injection Dependency? Если при использовании рамки DI (например, Ninject или Unity) вы можете определить экземпляр по умолчанию для каждого интерфейса, а затем использовать его следующим образом:

(если у вас есть интерфейс IWeapon и Sword реализует его)

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

Но Ninject (и большинство других фреймворков IoC) может делать некоторые более умные вещи, например: пусть скажем, что у нас есть класс Warrior, который принимает IWeapon как параметр в его конструкторе. Мы можем получить экземпляр Warrior из Ninject:

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

Ninject передаст реализацию IWeapon, указанную в конструкторе Warrior, и вернет новый экземпляр.

Кроме этого, я не знаю какой-либо функции на языке, которая допускает такое поведение.