2010-05-21 4 views
1

У меня есть метод, с которым я передаю IEnumerable<TModel>. Затем, в зависимости от типа TModel, метод выполняет набор инструкций, как показано ниже:C# Получить тип IEnumerable <TModel>

public void MyMethod<TModel>(IEnumerable<TModel> items) where TModel : class 
    { 
     int operationType; 
     switch (typeof(TModel)) 
     { 
      case typeof(MyModelOne): 
       operationType = 1; 
       break; 
      case typeof(MyModelTwo): 
       operationType = 2; 
       break; 
      case typeof(MyModelThree): 
       operationType = 3; 
       break; 
      default: 
       throw new Exception("The collection model passed to MyMethod is not recognized"); 
     } 
     ... 
    } 

Это не работает, я получаю ошибку:

Там нет переменного приложения или memeber «TModel»

ответ

6

Вы не можете включить переменную Type. Замените его каскадным сообщением if.

if (typeof(TModel) == typeof(MyModelOne)) { 
    operationType = 1; 
} else if (typeof(TModel) == typeof(MyModelTwo)) { 
    operationType = 2; 
} // ... 
+3

+1, но хотя typeof() является быстрым и легким, вероятно, лучше и понятнее получать только один тип родового. То есть Тип type = typeof (TModel); if (type == typeof (MyModelOne)) {} – GenericTypeTea

+0

@GenericTypeTea: Да. К тому времени, когда я печатал второй 'if', я уже написал' typeof (TModel) == ... 'и не стал возвращаться :) Скорее всего, это не повлияет. –

+1

Нет, будет означать, что он сидит на корточках в великой схеме вещей. Просто быть разборчивым, потому что вы избили меня до ответа = P. – GenericTypeTea

1

switch заявления работают только постоянные значения, такие как строки, целые числа и других основных типов. Type не является постоянным значением, поэтому его нельзя использовать в блоке коммутатора.

Эквивалентная операция представляет собой блок операторов if или с использованием словаря с использованием Type.

0

Вы можете только switch по интегральным и строковым типам. В этом случае вам нужно будет использовать if/else.

1

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

Возможно, типы, которые вы хотите принять, могут реализовать один и тот же интерфейс, и вы можете совершать на них вызовы на основе интерфейса, а не проверять тип вручную. Например:

interface IDoesSomething 
{ 
    void DoSomething(); 
} 

void MyMethod<T>(IEnumerable<T> objects) 
    where T : IDoesSomething 
{ 
    foreach (T t in objects) 
    { 
    t.DoSomething(); 
    } 
} 
+0

http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/25/408925.aspx – RossFabricant

+0

Хорошая ссылка там - я абсолютно согласен с ним, хотя он может быть слишком «сварливым», поскольку он ставит его , Но я определенно рекомендую сделать шаг назад всякий раз, когда проблема просто не «ощущается» правильно, чтобы вы делали все правильно, а не просто делали что-то, чтобы сделать их. –

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