Вопрос по c#, generics – Интерфейс в качестве аргумента или общий метод, где - в чем разница?
=============================================================================================

Есть ли разница между:

А также

?

Каковы преимущества использования первого метода?

В то время как в вашем сценарии это практически то же самое (за исключением того факта, что при методе, принимающем параметр интерфейса, он будет преобразовывать конкретный объект в тип интерфейса), рассмотрим немного другой сценарий. Допустим, мы хотим, чтобы наш метод принимал только класс, который реализует два интерфейса`IMyInterface1` а также`IMyInterface2` и этот код не должен компилироваться:

Если мы создадим метод, который принимает интерфейс в качестве второго параметра, он не будет удовлетворять условию, поскольку он не ограничивает пользователя от отправки экземпляра класса, который реализует только один интерфейс, но не реализует второй интерфейс, как это делается для MyClass и IMyInterface2 в этом пример.

А какой интерфейс должен отправить пользователь? Он действительно не знает тип, который нужно отправить во время компиляции.

Это хорошее место, чтобы использовать общие и общие ограничения, и с другой стороны, мы не можем использовать один параметр интерфейса.



Как уже отмечалось, с пустыми методами, нет большой разницы в использовании.

Если вы загляните за кулисы, то увидите, что с помощью универсального метода .NET скомпилирует отдельный метод для каждого типа, с которым вы его вызываете. Это позволяет избежать бокса при вызове со структурой.

Большая разница возникает при использовании типа возврата.

`public T Method1<T>(class1 c, T obj) where T: IMyInterface`

а также

`public IMyinterface Method2(class1 c, IMyInterface obj)`

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

С неуниверсальной версией вы получите только значение типа`IMyInterface`, поэтому вы можете вызывать только те свойства или методы, которые являются частью`IMyInterface`.

**Это наиболее интересно в моей книге, когда используется с методами расширения и API в свободном стиле.**

Учитывая, что Tiger реализует ICanMove и ICanPounce, а Eagle реализует ICanMove и ICanFly, я могу вызвать вышеупомянутые методы расширения, которые применяются к исходному типу. Intellisense покажет .Fly () и .Move (), доступные для Eagle, и .Pounce () и .Move () для Tiger.

Вот как это выглядело бы, если бы вы реализовали Move неуниверсально:

Поскольку возвращается интерфейс ICanMove, компилятор не знает, что он изначально был Eagle или Tiger, и поэтому вы можете использовать только расширения, методы или свойства, которые являются частью интерфейса ICanMove.



Там нет большой разницы для`void` методы.

равно

где`t` должно быть`Imyinterface`.

Так что если вам нужно передать некоторые`Type` к вашему методу, и вам нужно применить некоторые ограничения к этому`Type` во время компиляции используйте универсальный метод.



Использование универсального метода дает вам различные возможности с небольшими изменениями подписи:

`public void Method1<T>(class1 c, T obj) where T:Imyinterface, new()`:  
Это позволяет создавать новые экземпляры типаT.`public T Method1<T>(class1 c, T obj) where T:Imyinterface`:  
Это позволяет вам использовать метод без приведения его возвращаемого значения при необходимости.`public void Method1<T>(class1 c, ref T obj) where T:Imyinterface`:  
Это позволяет вам придать новое значение`obj`Ссылка. То же относится и к`out`.Это невозможно с не универсальной версией.