Похоже, что в этом случае вы пытаетесь избежать бокса? Трудно сказать без дополнительной информации, но для этого конкретного примера было бы гораздо проще и, вероятно, менее подвержено ошибкам просто использовать перегрузку методов:
void Assign(out string value)
{
//...
}
void Assign(out int value)
{
//...
}
В целях изучения, в частности, что является неправильным , вам необходимо привести значение к объекту перед преобразованием его в универсальный тип:
(T)(object)"hello world!";
Какой IMO довольно неприятный и должен быть последним средством - конечно, не делает ваш код чище.
Всякий раз, когда вы выполняете проверку типов общих параметров, это хороший признак того, что обобщенные значения не являются правильным решением вашей проблемы. Выполнение общих проверок типов параметров делает ваш код более сложным, а не проще. Это делает один метод ответственным за различное поведение, основанное на типе, вместо серии отдельных методов, которые легко изменить без случайного влияния на другие. См. Принцип единой ответственности .