É provável que seja uma pergunta iniciante, mas o Google surpreendentemente não forneceu uma resposta.
Eu tenho esse método bastante artificial
T HowToCast<T>(T t)
{
if (typeof(T) == typeof(string))
{
T newT1 = "some text";
T newT2 = (string)t;
}
return t;
}
Vindo de um background em C ++, esperava que isso funcionasse. No entanto, ele falha ao compilar com "Não é possível converter implicitamente o tipo 'T' em cadeia de caracteres" e "Não é possível converter o tipo 'T' em cadeia de caracteres" para as duas atribuições acima.
Ou estou fazendo algo conceitualmente errado ou apenas tenho a sintaxe errada. Por favor, ajude-me a resolver este.
Obrigado!
typeof(T) == typeof(string)
é resolvida no tempo de execução, não no tempo de compilação. Portanto, a seguinte linha no bloco é inválida.Respostas:
Mesmo que seja dentro de um
if
bloco, o compilador não sabe queT
éstring
.Portanto, não permite que você faça o elenco. (Pela mesma razão que você não pode lançar
DateTime
astring
)Você precisa converter para
object
, (para o qual qualquer umT
pode converter) e de lá parastring
(já queobject
pode ser convertido parastring
).Por exemplo:
fonte
T
:var isBlank = (userDefinedValue is string) && String.IsNullOrWhiteSpace(userDefinedValue as string);
Ambas as linhas têm o mesmo problema
O compilador não sabe que T é uma string e, portanto, não tem como saber como atribuir isso. Mas desde que você verificou, basta forçá-lo com
você não precisa converter ot, pois já é uma string, também precisa adicionar a restrição
fonte
Eu sei código semelhante que o OP postou nesta pergunta a partir de analisadores genéricos. De uma perspectiva de desempenho, você deve usar
Unsafe.As<TFrom, TResult>(ref TFrom source)
, que pode ser encontrado no pacote System.Runtime.CompilerServices.Unsafe NuGet. Evita boxe para tipos de valor nesses cenários. Também acho queUnsafe.As
resulta em menos código de máquina produzido pelo JIT do que em duas vezes (usando(TResult) (object) actualString
), mas ainda não o verifiquei.Unsafe.As
será substituído pelo JIT por instruções eficientes do código da máquina, como você pode ver no repo oficial do CoreFX:fonte
Se você está verificando tipos explícitos, por que está declarando essas variáveis como
T
's'?fonte
T
.object
valores, com tipos derivados que armazenamstring
valores. Suponha que esses campos também tenham um valor "DefaultIfNotProvided", portanto, é necessário verificar se o valor fornecido pelo usuário (que pode ser um objeto ou uma string ou mesmo uma primitiva numérica) é equivalente adefault(T)
. Seqüência de caracteres pode ser tratada como um caso especial em que uma seqüência de caracteres em branco / espaço em branco é tratada da mesma forma que o padrão (T); portanto, você pode verificar seT userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace(userValue as string);
.Você também receberá esse erro se tiver uma declaração genérica para sua classe e seu método. Por exemplo, o código mostrado abaixo fornece esse erro de compilação.
Este código é compilado (note T removido da declaração do método):
fonte
Mude esta linha:
Para esta linha:
fonte