Вероятно, это вопрос новичка, но на удивление Google не дал ответа.
У меня есть этот довольно искусственный метод
T HowToCast<T>(T t)
{
if (typeof(T) == typeof(string))
{
T newT1 = "some text";
T newT2 = (string)t;
}
return t;
}
Исходя из опыта C ++, я ожидал, что это сработает. Тем не менее, он не может быть скомпилирован с «Не удается неявно преобразовать тип« T »в строку» и «Не удается преобразовать тип« T »в строку» для обоих вышеупомянутых назначений.
Я либо делаю что-то концептуально неправильно, либо просто у меня неправильный синтаксис. Пожалуйста, помогите мне разобраться с этим.
Спасибо!
typeof(T) == typeof(string)
разрешается во время выполнения, а не во время компиляции. Таким образом, следующая строка в блоке недействительна.Ответы:
Даже если он находится внутри
if
блока, компилятор не знает, что этоT
такоеstring
.Следовательно, он не позволяет вам разыгрывать. (По той же причине , что вы не можете бросить
DateTime
вstring
)Вам нужно привести к
object
, (который любойT
может привести к), а оттуда кstring
(так какobject
можно привести кstring
).Например:
источник
T
:var isBlank = (userDefinedValue is string) && String.IsNullOrWhiteSpace(userDefinedValue as string);
Обе линии имеют одинаковую проблему
Компилятор не знает, что T является строкой, и поэтому не может знать, как его назначить. Но так как вы проверили, вы можете просто заставить его
вам не нужно приводить t, так как это уже строка, также нужно добавить ограничение
источник
Я знаю похожий код, который ОП выложил в этом вопросе из универсальных парсеров. С точки зрения производительности, вы должны использовать
Unsafe.As<TFrom, TResult>(ref TFrom source)
, который можно найти в пакете System.Runtime.CompilerServices.Unsafe NuGet. Это позволяет избежать упаковки для типов значений в этих сценариях. Я также думаю, что этоUnsafe.As
приводит к меньшему количеству машинного кода, создаваемого JIT, чем приведение дважды (с использованием(TResult) (object) actualString
), но я этого не проверял.Unsafe.As
будет заменен JIT с эффективными инструкциями машинного кода, как вы можете увидеть в официальном репозитории CoreFX:источник
Если вы проверяете явные типы, почему вы объявляете эти переменные как
T
s?источник
T
.object
значения, с производными типами, в которых хранятсяstring
значения. Предположим, что эти поля также имеют значение «DefaultIfNotProvided», поэтому вам необходимо проверить, эквивалентно ли предоставленное пользователем значение (которое может быть объектом, строкой или даже числовым примитивом)default(T)
. Строка может рассматриваться как особый случай, когда пустая строка / пробел обрабатывается так же, как по умолчанию (T), поэтому вы можете проверить, есть лиT userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace(userValue as string);
.Вы также получите эту ошибку, если у вас есть общее объявление для вашего класса и вашего метода. Например, приведенный ниже код выдает эту ошибку компиляции.
Этот код компилируется (примечание T удалено из объявления метода):
источник
Измените эту строку:
Для этой строки:
источник