He visto a muchas personas usar el siguiente código:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Pero sé que también podrías hacer esto:
if (obj1.GetType() == typeof(int))
// Some code here
O esto:
if (obj1 is int)
// Some code here
Personalmente, siento que el último es el más limpio, pero ¿hay algo que me falta? ¿Cuál es el mejor para usar, o es una preferencia personal?

as!asno es realmente comprobación de tipos, aunque ...ases sin duda una forma de verificación de tipo, ¡tanto comoises! Se usa de manera efectivaisdetrás de escena y se usa en todo el lugar en MSDN en lugares donde mejora la limpieza del código versusis. En lugar de verificarisprimero, una llamada aasestablece una variable escrita que está lista para su uso: si es nula, responda adecuadamente; de lo contrario, proceda. Ciertamente, algo que he visto y usado bastante.as/is(cubierto en stackoverflow.com/a/27813381/477420 ) suponiendo que funcione semánticamente para su caso.GetTypemétodo al que se está vinculando está enSystem.Reflection.Assemblyun método completamente diferente e irrelevante aquí.Respuestas:
Todos son diferentes
typeoftoma un nombre de tipo (que especifique en tiempo de compilación).GetTypeobtiene el tipo de tiempo de ejecución de una instancia.isdevuelve verdadero si una instancia está en el árbol de herencia.Ejemplo
Si. T siempre es el tipo de expresión. Recuerde, un método genérico es básicamente un montón de métodos con el tipo apropiado. Ejemplo:
fuente
new Dog().GetType() is Animaldevuelve falso (y su otra versión también) ya que.GetType()devuelve un objeto de tipoType, yTypeno es unAnimal.Úselo
typeofcuando desee obtener el tipo en el momento de la compilación . ÚseloGetTypecuando desee obtener el tipo en el momento de la ejecución . Rara vez hay casos para usar,isya que hace un lanzamiento y, en la mayoría de los casos, terminas lanzando la variable de todos modos.Hay una cuarta opción que no ha considerado (especialmente si también va a lanzar un objeto al tipo que encuentre); eso es para usar
as.Esto solo usa un molde
mientras que este enfoque:requiere dos .Actualización (enero de 2020):
Ejemplo:
fuente
istodavía se realiza un reparto?typeof(), y esta respuesta no sugiere que pueda. En su lugar, pasa el tipo, es decir,typeof(string)funciona,typeof("foo")no.isrealice el elenco como tal, sino una operación bastante especial en IL.if (obj is Foo foo) { /* use foo here */ }1)
Esto es ilegal, porque
typeofsolo funciona en tipos, no en variables. Supongo que obj1 es una variable. Por lo tanto, de esta maneratypeofes estático y funciona en tiempo de compilación en lugar de tiempo de ejecución.2)
Esto es
truesiobj1es exactamente de tipoint. Siobj1deriva deint, la condición if seráfalse.3)
Esto es
truesiobj1es unint, o si deriva de una clase llamadaint, o si implementa una interfaz llamadaint.fuente
Esto es un error El operador typeof en C # solo puede tomar nombres de tipos, no objetos.
Esto funcionará, pero quizás no como era de esperar. Para los tipos de valor, como ha mostrado aquí, es aceptable, pero para los tipos de referencia, solo devolvería verdadero si el tipo era exactamente el mismo tipo, no otra cosa en la jerarquía de herencia. Por ejemplo:
Esto se imprimiría
"o is something else", porque el tipo deoesDog, noAnimal. Sin embargo, puede hacer que esto funcione si usa elIsAssignableFrommétodo de laTypeclase.Sin embargo, esta técnica aún deja un gran problema. Si su variable es nula, la llamada a
GetType()arrojará una NullReferenceException. Entonces, para que funcione correctamente, harías:Con esto, tiene un comportamiento equivalente de la
ispalabra clave. Por lo tanto, si este es el comportamiento que desea, debe usar laispalabra clave, que es más legible y más eficiente.Sin embargo, en la mayoría de los casos, la
ispalabra clave todavía no es lo que realmente desea, porque generalmente no es suficiente saber que un objeto es de cierto tipo. Por lo general, desea utilizar ese objeto como una instancia de ese tipo, que también requiere lanzarlo. Y entonces puede que te encuentres escribiendo código como este:Pero eso hace que el CLR verifique el tipo de objeto hasta dos veces. Lo verificará una vez para satisfacer al
isoperador, y si deohecho es unAnimal, lo haremos verificar nuevamente para validar el lanzamiento.Es más eficiente hacer esto en su lugar:
El
asoperador es un elenco que no lanzará una excepción si falla, sino que regresaránull. De esta manera, el CLR verifica el tipo de objeto solo una vez, y después de eso, solo necesitamos hacer una verificación nula, que es más eficiente.Pero cuidado: muchas personas caen en una trampa con
as. Debido a que no arroja excepciones, algunas personas lo consideran un yeso "seguro", y lo usan exclusivamente, evitando los lanzamientos regulares. Esto lleva a errores como este:En este caso, el desarrollador está asumiendo claramente que
ohabrá siempre ser unaAnimal, y siempre que su suposición es correcta, todo funciona bien. Pero si están equivocados, entonces lo que terminan aquí es aNullReferenceException. Con un reparto regular, habrían obtenido unInvalidCastExceptionen su lugar, que habría identificado más correctamente el problema.A veces, este error puede ser difícil de encontrar:
Este es otro caso en el que el desarrollador claramente espera
oserloAnimalcada vez, pero esto no es obvio en el constructor, dondeasse usa el elenco. No es obvio hasta que llegue alInteractmétodo, dondeanimalse espera que el campo se asigne positivamente. En este caso, no solo termina con una excepción engañosa, sino que no se produce hasta potencialmente mucho más tarde que cuando ocurrió el error real.En resumen:
Si solo necesita saber si un objeto es o no de algún tipo, úselo
is.Si necesita tratar un objeto como una instancia de cierto tipo, pero no está seguro de que el objeto sea de ese tipo, utilícelo
asy verifiquenull.Si necesita tratar un objeto como una instancia de cierto tipo, y se supone que el objeto es de ese tipo, use un molde regular.
fuente
o is Animal, lo que requiere que el CLR verifique si el tipo de la variableoes anAnimal. La segunda vez que verifica es cuando emite la declaración((Animal)o).Speak(). En lugar de verificar dos veces, verifique una vez usandoas.Si está utilizando C # 7, entonces es hora de actualizar la excelente respuesta de Andrew Hare. La coincidencia de patrones ha introducido un buen acceso directo que nos da una variable tipeada dentro del contexto de la instrucción if, sin requerir una declaración / conversión y verificación por separado:
Esto parece bastante decepcionante para un solo elenco como este, pero realmente brilla cuando tienes muchos tipos posibles entrando en tu rutina. La siguiente es la forma antigua de evitar lanzar dos veces:
Trabajar para reducir este código tanto como sea posible, así como para evitar la duplicación de lanzamientos del mismo objeto siempre me ha molestado. Lo anterior está bien comprimido con un patrón que coincide con lo siguiente:
EDITAR: se actualizó el nuevo método más largo para usar un interruptor según el comentario de Palec.
fuente
switchEn este caso, es aconsejable declaración con coincidencia de patrones .if (obj1 is int integerValue) { integerValue++; }Tenía una
Typepropiedad para comparar y no podía usaris(me gustamy_type is _BaseTypetoLookFor), pero podía usar estos:Tenga en cuenta que
IsInstanceOfTypeyIsAssignableFromregresetrueal comparar los mismos tipos, donde IsSubClassOf regresaráfalse. YIsSubclassOfno funciona en interfaces, donde los otros dos lo hacen. (Vea también esta pregunta y respuesta ).fuente
yo prefiero es
Dicho esto, si estás usando es probable que no usando la herencia correctamente.
Asuma que Persona: Entidad, y ese Animal: Entidad. Feed es un método virtual en Entity (para hacer feliz a Neil)
Más bien
fuente
Creo que el último también analiza la herencia (por ejemplo, Dog is Animal == true), que es mejor en la mayoría de los casos.
fuente
Depende de lo que estoy haciendo. Si necesito un valor bool (por ejemplo, para determinar si voy a convertir a un int), lo usaré
is. Si realmente necesito el tipo por alguna razón (por ejemplo, para pasar a algún otro método) lo usaréGetType().fuente
El último es más limpio, más obvio, y también busca subtipos. Los otros no verifican el polimorfismo.
fuente
Se usa para obtener el objeto System.Type para un tipo. Una expresión typeof toma la siguiente forma:
Esta muestra utiliza el método GetType para determinar el tipo que se utiliza para contener el resultado de un cálculo numérico. Esto depende de los requisitos de almacenamiento del número resultante.
fuente
fuente
Puede usar el operador "typeof ()" en C # pero necesita llamar al espacio de nombres usando System.IO; Debe usar la palabra clave "is" si desea verificar un tipo.
fuente
typeofno está definido en un espacio de nombres, es una palabra clave.System.IONo tiene nada que ver con esto.Prueba de rendimiento typeof () vs GetType ():
Resultados en modo de depuración:
Resultados en modo de liberación:
fuente
DateTimeno debe usarse si le preocupan los tiempos por debajo de 100 ms , ya que usa el marco de tiempo del sistema operativo. En comparación conStopwatch, que utiliza los procesadoresTick, la resolución utilizada por aDateTimeen Win7 es de 15 ms.