Если вам нужно знать о полях или свойствах типа, чтобы «сохранить или обновить», вы можете использовать отражение. Таким образом, класс останется действительно общим.
Если в рамках вашего SaveOrUpdate
метода вы хотите написать постоянно расширяющийся переключатель, эквивалентный:
if (it's type A) { deal with type A }
else if (it's type B) { deal with type B }
... and so on
Тогда вы делаете это "неправильно". Этот класс не является действительно универсальным в своем параметре типа. Он работает только с указанным вами набором типов. Я говорю «неправильно» в кавычках, потому что в некоторых ситуациях это может быть лучше, чем доступные альтернативы, но это нежелательно. Если у вас есть запасной вариант для всех других типов, поэтому он всегда работает, то это может быть хорошим способом иметь специальные случаи для определенных типов.
Однако вы можете сделать такой тест или кастинг. С параметром неограниченного типа T
сначала необходимо привести его к object
:
var eitherStringOrNull = (string)((object)somethingOfTypeT);
При использовании ключевого слова as
вам не нужно это дополнительное приведение к object
.
var eitherStringOrNull = somethingOfTypeT as string;
if (eitherStringOrNull != null)
{
.. it was a string, so we can use it as such
}
Но еще лучше, если есть общий базовый класс, ProductDetail
, для всех видов классов деталей продукта, тогда используйте его как ограничение для T
:
public class ProductServiceGeneric<T> : IProductServiceGeneric<T>
where T : ProductDetail
Я думаю, что при этом рекомендуется использовать более значимое имя для параметра типа, например TProductDetail
.
Если вы сделаете это, то компилятор должен позволить вам "привести вниз" к чему-то, производному от ProductDetail
, без необходимости сначала приводить к object
.