2013-11-13 5 views
6

Каковы аргументы для использования той или иной из этих двух реализаций метода (в Пример класс)?Параметр метода: Интерфейс VS Общий тип

public interface IInterface 
{ 
    void DoIt(); 
} 

public class Example 
{ 
    public void MethodInterface(IInterface arg) 
    { 
     arg.DoIt(); 
    } 

    public void MethodGeneric<T>(T arg) where T: IInterface 
    { 
     arg.DoIt(); 
    } 
} 

PS: Если метод возвращает IInterface или T я бы выбрал «общий» способ избежать дальнейшего литья по типу T при необходимости.

+1

Я не понял ваш вопрос. Вы спрашиваете, какая практика лучше? –

+1

Я не думаю, что это имеет реальное значение в этом случае, но я бы сказал, что использование дженериков здесь неоправданно усложняет ситуацию и, вероятно, добавляет накладные расходы на определение функции. – poke

+0

@Saeed Neamati: да, лучшая практика, но, прежде всего, влияние на дизайн, компиляцию, дальнейшая проблема, с которой мы можем столкнуться с тем или иным способом, или, может быть, одно из этих решений ужасно неправильно по какой-то причине я не могу заметить. – Askolein

ответ

4

Оба кажутся такими же, но на самом деле нет.

Generic версия не будет ЯЩИК ValueType при передаче где, как не общий вариант требует «бокс»

Вот небольшой пример программы и соответствующий IL, который демонстрирует ситуацию

void Main() 
{ 
    Example ex = new Example(); 
    TestStruct tex = new TestStruct(); 
    ex.MethodGeneric(tex); 
    ex.MethodInterface(tex); 
} 
public interface IInterface 
{ 
    void DoIt(); 
} 

public class Example 
{ 
    public void MethodInterface(IInterface arg) 
    { 
     arg.DoIt(); 
    } 

    public void MethodGeneric<T>(T arg) where T : IInterface 
    { 
     arg.DoIt(); 
    } 
} 

internal struct TestStruct : IInterface 
{ 
    public void DoIt() 
    { 

    } 
} 

Ниже соответствующая часть IL генерируется

IL_0001: newobj  UserQuery+Example..ctor 
IL_0006: stloc.0  // ex 
IL_0007: ldloca.s 01 // tex 
IL_0009: initobj  UserQuery.TestStruct 
IL_000F: ldloc.0  // ex 
IL_0010: ldloc.1  // tex 
IL_0011: callvirt UserQuery+Example.MethodGeneric 
IL_0016: nop   
IL_0017: ldloc.0  // ex 
IL_0018: ldloc.1  // tex 
IL_0019: box   UserQuery.TestStruct //<--Box opcode 
IL_001E: callvirt UserQuery+Example.MethodInterface 

Хотя это вопрос предпочтений, в то время MethodGeneric является одним WH ич будет работать лучше в случае «типов значений»

3

Я предлагаю интерфейс передачи в качестве простого параметра, вместо того, чтобы использовать общий подход, по этим причинам:

  1. Simpler дизайн, что приводит к лучшей ремонтопригодности
  2. Более читаемый код, меньший профессиональные знания
  3. Улучшенная поддержка Dependency Injection и IoC
  4. нет отражения (я не уверен в этом, я собираюсь предоставить доказательства, потому что дженерики использовать отражение, чтобы понять тип)
+1

Интерфейс используется в обоих случаях, поэтому этот ответ неоднозначен. –

+0

@GrantThomas, спасибо, что заметили. Обновлен ответ. –

Смежные вопросы