2017-02-15 17 views
5

Рассмотрят следующий интерфейс:Внедрение универсального интерфейса отсутствует новое ограничение

public interface IFoo 
{ 
    M Bar<M>(); 
} 

Попытки осуществить это с

class Foo : IFoo 
{ 
    public M Bar<M>() 
    { 
     return new M(); 
    } 
} 

не работает, компилятор жалуется M не хватает new() ограничения.

Когда я добавить ограничение, как в

class Foo : IFoo 
{ 
    public M Bar<M>() where M : new() 
    { 
     return new M(); 
    } 
} 

этого еще не делает трюк, так как ограничения Foo.Bar не соответствуют ограничениям метода интерфейса теперь (и я не могу изменить что).

documentation for the compiler error CS0425 говорит

Чтобы избежать этой ошибки, убедитесь, где положение идентично в обоих деклараций, либо реализуют интерфейс явно.

Если «реализация интерфейса явно» является решением: как это сделать?

+0

Это потому, что вам нужно вернуть новый или вам нужно что-то вернуть, когда больше нечего возвращать? Будет ли «default (M)» быть достаточно хорошим? Он возвращает значение по умолчанию для данного генерического типа, для ссылок это «null». В противном случае для создания экземпляра вам понадобятся деревья выражений или отражение. –

ответ

6

Если вы не можете изменить определение интерфейса, вы должны избегать использования new M(); - использовать Activator.CreateInstance вместо:

class Foo : IFoo 
{ 
    public M Bar<M>() 
    { 
     return Activator.CreateInstance<M>(); 
    } 
} 

Конечно, теперь вы можете столкнуться с ошибкой во время выполнения, если нет конструктора без параметров для M, но это неизбежно (опять же, потому что мы не можем изменить общие ограничения).


Re: документация:

реализуют интерфейс явно.

Я думаю, что они пытаются получить в здесь «, если у вас есть метод базового класса, который имеет один набор общих ограничений, и вы хотите, чтобы реализовать интерфейс, который имеет другой набор ограничений для метода с тем же именем, явная реализация - это один из путей этого связывания ».

+0

Благодарим вас за интерпретацию документации. Возможно, вы правы. Я был в режиме мышления: «документация объясняет, что я сделал неправильно, и показывает выход из положения», что привело меня к неправильному пути. – mkluwe

0

Вы можете создать явную реализацию интерфейса, щелкнув правой кнопкой мыши в интерфейсе в классе, который должен реализовать его и выбрать «реализовать явно». Названия методов должны быть перечеркнуты с именем интерфейса.

5

Внедрение интерфейса явно не решение. Компилятор просто говорит вам, что если вам нужен общий метод Bar с этим ограничением, тогда явным образом реализую интерфейс так, что могут использоваться как версии Bar, но это, очевидно, не решение, которое вы ищете.

Единственные решения:

  1. Внедрение универсального типа ограничений в интерфейсе.
  2. Создайте новый M через отражение: Activator.CreateInstance и оплатите цену потери типа безопасности во время компиляции; ничто не заставляет M иметь конструктор без параметров.
+0

Ничто не гарантирует, что 'M' является даже типом, который вы можете создать, может быть интерфейсом. –

+0

@AdamHouldsworth Ну да, у любого несовместимого типа отсутствует удобный конструктор без параметров. Я не вижу разницы, которые вы пытаетесь сделать. – InBetween

+0

Нет никакой разницы, просто указывая на то, что ни один конструктор без параметров не является наименьшей из проблем - наблюдение больше всего на свете. Просто напоминает мне, почему я стараюсь не создавать или использовать такие интерфейсы. –