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

Интерфейс как аргумент или общий метод, где - в чем разница?

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

public void Method1<T>(class1 c, T obj) where T:Imyinterface

и

public void Method2(class1 c, Imyinterface obj)

?

В чем преимущества первого метода?

4b9b3361

Ответ 1

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

interface IMyInterface1 { }    

interface IMyInterface2 { }

class MyClass : IMyInterface1 { }

public void Method1<T>(Class1 c, T obj) where T : IMyInterface1, IMyInterface2
{

}

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

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

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

Ответ 2

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

  • 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.

Это невозможно в не общей версии.

Ответ 3

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

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

Большая разница возникает, когда вы используете возвращаемый тип.

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

и

public IMyinterface Method2(class1 c, IMyInterface obj)

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

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

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

public static T Move<T>(this T animal) where T : ICanMove
{
    return animal;
}

public static T Fly<T>(this T animal) where T : ICanFly
{
    return animal;
}

public static T Pounce<T>(this T animal) where T : ICanPounce
{

    return animal;
}

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

var birdie = new Eagle();

birdie
    .Move()
    .Fly()
    .Move()
    .Fly();

var kitty = new Tiger();

kitty
    .Move()
    .Pounce()
    .Move()
    .Pounce();

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

public static ICanMove Move<T>(this ICanMove animal) 
{
    return animal;
}

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

Ответ 4

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

public void Method1<T>(class1 c, T obj) where T : Imyinterface

равно

public void Method2(class1 c, Imyinterface obj, Type t)

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

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