Eu já vi muitas pessoas usarem o seguinte código:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Mas eu sei que você também pode fazer isso:
if (obj1.GetType() == typeof(int))
// Some code here
Ou isto:
if (obj1 is int)
// Some code here
Pessoalmente, sinto que o último é o mais limpo, mas há algo que estou perdendo? Qual é o melhor para usar ou é preferência pessoal?
as
!as
não é realmente verificação de tipo embora ...as
é certamente uma forma de verificação de tipo, tanto quantois
é! Ele efetivamente usais
nos bastidores e é usado em todo o MSDN em locais onde melhora a limpeza do códigois
. Em vez deis
procurar pela primeira vez, uma chamada paraas
estabelecer uma variável digitada pronta para uso: se for nula, responda adequadamente; caso contrário, continue. Certamente algo que eu já vi e usei bastante.as
/is
(abordado em stackoverflow.com/a/27813381/477420 ) assumindo que seus trabalhos semânticos funcionam para o seu caso.GetType
método ao qual você está vinculando éSystem.Reflection.Assembly
um método completamente diferente e irrelevante aqui.Respostas:
Todos são diferentes.
typeof
leva um nome de tipo (que você especifica em tempo de compilação).GetType
obtém o tipo de tempo de execução de uma instância.is
retorna true se uma instância estiver na árvore de herança.Exemplo
Sim. T é sempre qual é o tipo da expressão. Lembre-se, um método genérico é basicamente um monte de métodos com o tipo apropriado. Exemplo:
fonte
new Dog().GetType() is Animal
retorna false (e sua outra versão também), pois.GetType()
retorna um objeto do tipoType
eType
não é umAnimal
.Use
typeof
quando quiser obter o tipo no momento da compilação . UseGetType
quando quiser obter o tipo no tempo de execução . Raramente existem casos a serem usadosis
, pois são convertidos e, na maioria dos casos, você acaba convertendo a variável de qualquer maneira.Há uma quarta opção que você não considerou (especialmente se você também deseja converter um objeto para o tipo encontrado); isso é para usar
as
.Isso usa apenas um elenco,
enquanto esta abordagem:requer dois .Atualização (Jan 2020):
Exemplo:
fonte
is
ainda é possível executar uma conversão?typeof()
, e esta resposta não sugere que você pode. Você passa o tipo, ou seja,typeof(string)
funciona,typeof("foo")
não.is
interpreta elenco como tal, uma operação bastante especial em IL.if (obj is Foo foo) { /* use foo here */ }
1
Isso é ilegal, porque
typeof
funciona apenas em tipos, não em variáveis. Presumo que obj1 é uma variável. Portanto, dessa maneira,typeof
é estático e funciona em tempo de compilação, em vez de em tempo de execução.2)
Isto é,
true
seobj1
é exatamente do tipoint
. Seobj1
deriva deint
, a condição se seráfalse
.3)
Isto é
true
seobj1
é umint
, ou se deriva de uma classe chamadaint
, ou se implementa uma interface chamadaint
.fonte
Isto é um erro. O operador typeof em C # pode usar apenas nomes de tipos, não objetos.
Isso funcionará, mas talvez não como você esperaria. Para os tipos de valor, como você mostrou aqui, é aceitável, mas para os tipos de referência, ele só retornará true se o tipo for exatamente o mesmo tipo, e não outra coisa na hierarquia de herança. Por exemplo:
Isso imprimiria
"o is something else"
, porque o tipo deo
éDog
, nãoAnimal
. Você pode fazer isso funcionar, no entanto, se você usar oIsAssignableFrom
método daType
classe.Essa técnica ainda deixa um grande problema, no entanto. Se sua variável for nula, a chamada para
GetType()
lançará uma NullReferenceException. Então, para fazê-lo funcionar corretamente, você faria:Com isso, você tem um comportamento equivalente à
is
palavra - chave. Portanto, se esse é o comportamento que você deseja, use ais
palavra - chave, que é mais legível e mais eficiente.Na maioria dos casos, porém, a
is
palavra - chave ainda não é o que você realmente deseja, porque geralmente não é suficiente apenas saber que um objeto é de um determinado tipo. Geralmente, você deseja realmente usar esse objeto como uma instância desse tipo, o que exige a conversão também. E assim, você pode escrever código como este:Mas isso faz com que o CLR verifique o tipo do objeto até duas vezes. Ele irá checá-lo uma vez para satisfazer o
is
operador e, seo
for de fato umAnimal
, fazemos novamente o checagem para validar o elenco.É mais eficiente fazer isso:
O
as
operador é um elenco que não emitirá uma exceção se falhar, retornandonull
. Dessa forma, o CLR verifica o tipo de objeto apenas uma vez e, depois disso, precisamos fazer uma verificação nula, que é mais eficiente.Mas cuidado: muitas pessoas caem em uma armadilha
as
. Como não gera exceções, algumas pessoas pensam nele como um elenco "seguro" e o usam exclusivamente, evitando os lançamentos regulares. Isso leva a erros como este:Neste caso, o desenvolvedor está assumindo claramente que
o
irá sempre ser umaAnimal
, e desde que a sua hipótese é correta, tudo funciona bem. Mas se eles estão errados, então o que eles acabam com aqui é umNullReferenceException
. Com um elenco regular, eles teriam conseguido umInvalidCastException
lugar, o que teria identificado mais corretamente o problema.Às vezes, esse bug pode ser difícil de encontrar:
Este é outro caso em que o desenvolvedor espera claramente
o
estarAnimal
sempre, mas isso não é óbvio no construtor, onde oas
elenco é usado. Não é óbvio até que você chegue aoInteract
método, ondeanimal
se espera que o campo seja atribuído positivamente. Nesse caso, você não apenas acaba com uma exceção enganosa, mas é lançada até potencialmente muito mais tarde do que quando ocorreu o erro real.Em suma:
Se você só precisa saber se um objeto é ou não de algum tipo, use
is
.Se você precisar tratar um objeto como uma instância de um determinado tipo, mas não tiver certeza de que o objeto será desse tipo, use
as
e verifiquenull
.Se você precisar tratar um objeto como uma instância de um determinado tipo, e o objeto for desse tipo, use uma conversão regular.
fonte
o is Animal
, o que exige que o CLR verifique se o tipo da variávelo
é umAnimal
. A segunda vez que verifica é quando lança na declaração((Animal)o).Speak()
. Em vez de verificar duas vezes, verifique uma vez usandoas
.Se você estiver usando o C # 7, é hora de atualizar a ótima resposta de Andrew Hare. A correspondência de padrões introduziu um bom atalho que nos fornece uma variável digitada no contexto da instrução if, sem a necessidade de uma declaração / conversão e verificação separadas:
Isso parece bastante decepcionante para um elenco único como esse, mas realmente brilha quando você tem muitos tipos possíveis entrando em sua rotina. A seguir, é a maneira antiga de evitar transmitir duas vezes:
Trabalhar em torno da redução do código o máximo possível, além de evitar lançamentos duplicados do mesmo objeto, sempre me incomodou. O acima é bem compactado com o padrão correspondente ao seguinte:
EDIT: Atualizado o novo método mais longo para usar uma opção de acordo com o comentário do Palec.
fonte
switch
instrução com correspondência de padrões neste caso.if (obj1 is int integerValue) { integerValue++; }
Eu tinha uma
Type
propriedade -para comparar e não podia usaris
(comomy_type is _BaseTypetoLookFor
), mas poderia usá-las:Observe isso
IsInstanceOfType
eIsAssignableFrom
retornetrue
ao comparar os mesmos tipos, onde IsSubClassOf retornaráfalse
. EIsSubclassOf
não funciona em interfaces, onde os outros dois fazem. (Veja também esta pergunta e resposta .)fonte
Eu prefiro é
Dito isto, se você está usando é , você provavelmente está não usando herança corretamente.
Suponha que Pessoa: Entidade e esse Animal: Entidade. O feed é um método virtual na Entidade (para deixar Neil feliz)
Em vez
fonte
Acredito que o último também analise a herança (por exemplo, Dog is Animal == true), o que é melhor na maioria dos casos.
fonte
Depende do que estou fazendo. Se eu precisar de um valor bool (por exemplo, para determinar se vou converter para um int), usarei
is
. Se eu realmente precisar do tipo por algum motivo (por exemplo, para passar para outro método), usareiGetType()
.fonte
O último é mais limpo, mais óbvio e também verifica os subtipos. Os outros não verificam se há polimorfismo.
fonte
Usado para obter o objeto System.Type para um tipo. Uma expressão typeof assume o seguinte formato:
Este exemplo usa o método GetType para determinar o tipo usado para conter o resultado de um cálculo numérico. Isso depende dos requisitos de armazenamento do número resultante.
fonte
fonte
Você pode usar o operador "typeof ()" em C #, mas precisa chamar o espaço para nome usando System.IO; Você deve usar a palavra-chave "is" se desejar verificar um tipo.
fonte
typeof
não está definido em um espaço para nome, é uma palavra-chave.System.IO
não tem nada a ver com isso.Teste de desempenho typeof () vs GetType ():
Resultados no modo de depuração:
Resultados no modo de liberação:
fonte
DateTime
não deve ser usado se você estiver preocupado com tempos abaixo de 100 ms , pois ele usa o período de tempo do sistema operacional. Comparativamente comStopwatch
, que usa os processadoresTick
, a resolução usada por umDateTime
no Win7 é de 15ms.