2008-11-13 2 views
2

У меня проблемы с общим методом, который я пишу. Он имеет следующую подпись;Проблема с литьем в стандартном методе C#

public static ThingCollection<T> GetThings<T>(...) where T : Thing 

Существует несколько классов; ThingA, ThingB и ThingC, которые наследуются от Thing; и я хочу иметь код, подобный этому в методе.

var things = new ThingCollection<T>(); 

if (typeof(T) == typeof(Thing)) 
    foreach (var item in someCollection) 
    things.Add((T)new Thing(...)); 
else if (typeof(T) == typeof(ThingA)) 
    foreach (var item in someCollection) 
    things.Add((T)new ThingA(...)); 
else if (typeof(T) == typeof(ThingB)) 
    foreach (var item in someCollection) 
    things.Add((T)new ThingB(...)); 
else if (typeof(T) == typeof(ThingC)) 
    foreach (var item in someCollection) 
    things.Add((T)new ThingC(...)); 
else 
    throw new Exception("Cannot return things of type " + typeof(T).ToString()); 

return things; 

Проблема заключается в том, что я получаю лучший перегружен матч метода имеет недопустимые аргументы ошибку, если я не отбрасываю новые объекты. Добавление T-тэгов, как показано выше, отлично подходит для нового Thing(), но сообщает Невозможно преобразовать тип «ThingA» в «T» для других новых вызовов. Intellisense указывает, что T является Вещью, но я не понимаю, почему я не могу отбрасывать другие объекты в Thing, поскольку они наследуют от него.

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

ответ

7

Я не понимаю, что вы пытаетесь сделать с этим кодом.

Если вы хотите создать коллекцию вещей, в которой вы могли бы добавить любой тип класса, производный от Thing, ThingCollection не должен иметь Typename: он должен быть коллекцией для конкретных типов.

например, встраивание ThingCollection таким образом:

public class ThingCollection : List<Thing> {} 

теперь вы можете сделать

ThingCollection tc = new ThingCollection(); 
tc.Add(new ThingA()); 
tc.Add(new ThingB()); 
tc.Add(new ThingC()); 

Предполагая, конечно, что ThingA, ThingB и ThingC наследуются от Thing.

Или, возможно, вы хотите фильтровать производные типы вещей с помощью GetThings(), то есть хотите, чтобы вызов GetThings() возвращал ThingCollection.

+0

Это была большая помощь. Я боролся за то, чтобы справиться с дженериками, поскольку я не понимал, что мне не нужно создавать ThingCollection только потому, что он наследуется от общего списка. – 2008-11-13 14:56:50

2

Если они используют общий интерфейс (IThing), вы должны уметь это делать.

3

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

public static ThingCollection<T> GetThings<T>(...) where T : Thing, new() 
... 
... 
T item = new T(); 
item.Something = Whatever(); 

Или вы можете реализовать «ICloneable» класс интерфейса ИНТ Thing.

3

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

Чтобы избежать этого, вы можете использовать комбинацию словаря/стратегии или шаблон посетителя.

Если T ThingB, то отливка Th (T) ThingA недействительна, поэтому код действительно неправильный.

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

  • Нет связанных вопросов^_^