2015-03-23 7 views
1
interface IComponent { /*code*/ } 
interface IContent : IComponent { /*code*/ } 
interface IMedia : IComponent { /*code*/ } 
class A : IContent { /*code*/ } 
class B : IMedia { /*code*/ } 
class C : IContent, IMedia { /*code*/ } 

private static T GetComponent<T>(string itemTemplate) 
     where T : IComponent, new() 
{ 
    T component; 
    switch (itemTemplate) 
    { 
     case "template_1": 
      component = new A(); 
      break; 
     case "template_2": 
      component = new B(); 
      break; 
     case "template_3": 
      component = new C(); 
      break; 
     default: 
      throw new ArgumentOutOfRangeException("itemTemplate"); 
    } 
    return component; 
} 

Я получаю эти ошибки построения, где я создаю экземпляры производных типов:Дженерики не может преобразовать тип

Cannot implicitly convert type 'Objects.A' to 'T' 
Cannot implicitly convert type 'Objects.B' to 'T' 
Cannot implicitly convert type 'Objects.C' to 'T' 

EDIT: Параметр ItemTemplate является имя шаблона в Sitecore Пункт.

ответ

4

Причина, почему C# компилятор предотвращает есть тот случай, когда вы можете позвонить:

GetComponent<A>("condition_2"); 

Этот вызов не будет удовлетворять компиляторы, потому что «condition_2» создаст новый B, а не А.

поскольку вы используете только Generic тип T в качестве возвращаемого типа, я хотел бы предложить, что вы не должны использовать Generic здесь просто как по образцу фабрики:

private static IComponent GetComponent(string condition) 
{ 
    IComponent component; 
    switch (condition) 
    { 
     case "condition_1": 
      component = new A(); 
      break; 
     case "condition_2": 
      component = new B(); 
      break; 
     case "condition_3": 
      component = new C(); 
      break; 
     default: 
      throw new ArgumentOutOfRangeException("condition"); 
    } 
    return component; 
} 
8

Вам необходимо наложить на T - но сначала, несколько досадно, вам нужно отдать object из-за правил вокруг конверсий, чтобы ввести параметры в C#.

Я бы лично избавиться от локальных переменных, хотя, которая не помогает вам:

private static T GetComponent<T>(string condition) 
     where T : IComponent, new() 
{ 
    switch (condition) 
    { 
     case "condition_1": 
      return (T) (object) new A(); 
     case "condition_2": 
      return (T) (object) new B(); 
     case "condition_3": 
      return (T) (object) new C(); 
     default: 
      throw new ArgumentException("condition"); 
    } 
} 

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

В принципе, неясно, какое отношение имеет состояние к запрашиваемому типу.

+4

Или еще лучше, вернуться IComponent –

+0

@SteveCzetty: Действительно - я фактически не проверял эту часть вопроса. Будет редактировать. –

+0

@JonSkeet Обновленный вопрос, чтобы ответить на ваш вопрос о состоянии –