2013-12-05 3 views
0

У меня есть общий метод, который я хотел бы передать либо ссылочным типом, либо bool.Тестирование значений bool с общим T

private void Test<T>(T value) 
{ 
    if(typeof(T)) == typeof(bool)) 
    { 
     if(value == false) 
      // do something 
     else if (value == null) 
      // do something else 
    } 
} 

, но я получаю эту ошибку компиляции времени «Оператор ==' cannot be applied to operands of type T 'и` Ьоо». Есть ли простое решение для этого (желательно без использования Reflection)?

Обновление: Если оно заключено в цикл foreach, будет ли неявный листинг? Я все равно получаю ту же ошибку компиляции.

private void Test<T>(T[] values) 
{ 
    foreach(T value in values) 
    { 
     if(typeof(T)) == typeof(bool)) 
     { 
      if(value == false) 
       // do something 
     } 
     else if (value == null) 
       // do something else 
    } 
} 
+1

T является аргументом типа и может быть классом или структурой. Таким образом, com piler не позволит вам выполнять действия, которые не существуют в классах и структурах. (Боковое примечание: 'значение == false' ->'! Value') –

+1

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

ответ

1

Вам нужно уродливый двойной бросок, как это:

private void Test<T>(T value) 
{ 
    if(typeof(T) == typeof(bool)) 
    { 
     if((bool)(object)value) 
      // do something 
     else if (!(bool)(object)value) 
      // do something else 
    } 
} 

То же самое относится внутри цикла:

private void Test<T>(T[] values) 
{ 
    foreach(T value in values) 
    { 
     if(typeof(T) == typeof(bool)) 
     { 
      if (!(bool)(object)value) 
       // do something 
     } 
     else if (value == null) 
       // do something else 
    } 
} 

Хотя, это намного больше сравнений, чем вам нужно. Это было бы более эффективным:

private void Test<T>(params T[] values) 
{ 
    if(typeof(T) == typeof(bool)) 
    { 
     foreach(bool b in values.Cast<bool>()) 
     { 
      if (!b) 
       // do something 
     } 
    } 
    else 
    { 
     foreach(T value in values) 
     { 
      if (value == null) 
      // do something else 
     } 
    } 
} 

Также нет, если do something и do something else то же самое, вы можете упростить это еще больше:

private void Test<T>(params T[] values) 
{ 
    foreach(T value in values) 
    { 
     if (value == default(T)) 
      // do something 
    } 
} 

Следует отметить, однако, что тестирование для типов внутри общего метода и использование разных стратегий для разных аргументов типа - довольно плохой запах кода. Вероятно, вам было бы лучше предоставить другую перегрузку для bool или любой другой тип параметра, для которого вам потребуется специальная обработка.

+1

Спасибо, но я получаю следующую ошибку при кастинге: «Невозможно преобразовать тип« T »в« bool »« – user2994682

+1

@ user2994682 Используем ли мы последнюю версию моего кода (с двойным литом - '(bool) (object) value')? вы не должны видеть эту ошибку. –

2

Вам все еще нужно, чтобы бросить, даже если вы проверили тип, и ваше else заявление будет не пожар:

private void Test<T>(T value) 
{ 
    if(typeof(T)) == typeof(bool)) 
    { 
     if((bool)value == false) 
      // do something 
     else if (value == null) // this will never be true for a bool! 
      // do something else 
    } 
} 
6

Используйте is оператор:

private void Test<T>(T value) 
{ 
    if(value is bool) 
    { 
     ... 
    } 
} 

или as оператора:

private void Test<T>(T value) 
{ 
    bool? boolValue = value as bool; 
    if (boolValue != null) { 
     // do something with boolValue, which can never be null if value is of type bool 
    } 
    else { 
     // do something with value, which is not a boolean 
    } 
} 
+1

Хорошая точка, но не решает проблему, к которой относится OP. –

+0

Спасибо за то, что указали это, обновили, чтобы включить вариацию оператора 'as', которая решит проблему делать что-то со значением. – mayabelle

+1

@mayabelle * Оператор as должен использоваться с ссылочным типом или типом с нулевым значением ('bool' - тип значения, не допускающего nullable) * –

2

В зависимости от того, как вы вызываете этот метод, вы можете просто создать перегрузку принимая bool:

private void Test(bool b) 
{ 
    if(! b) 
    { 
     //do something 
    } 
} 

private void Test<T>(T value) where T : class 
{ 
    if(value == null) 
    { 
     //do something else 
    } 
} 
Смежные вопросы