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
!as
no es realmente comprobación de tipos, aunque ...as
es sin duda una forma de verificación de tipo, ¡tanto comois
es! Se usa de manera efectivais
detrá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 verificaris
primero, una llamada aas
establece 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.GetType
método al que se está vinculando está enSystem.Reflection.Assembly
un método completamente diferente e irrelevante aquí.Respuestas:
Todos son diferentes
typeof
toma un nombre de tipo (que especifique en tiempo de compilación).GetType
obtiene el tipo de tiempo de ejecución de una instancia.is
devuelve 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 Animal
devuelve falso (y su otra versión también) ya que.GetType()
devuelve un objeto de tipoType
, yType
no es unAnimal
.Úselo
typeof
cuando desee obtener el tipo en el momento de la compilación . ÚseloGetType
cuando desee obtener el tipo en el momento de la ejecución . Rara vez hay casos para usar,is
ya 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
is
todaví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.is
realice 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
typeof
solo funciona en tipos, no en variables. Supongo que obj1 es una variable. Por lo tanto, de esta maneratypeof
es estático y funciona en tiempo de compilación en lugar de tiempo de ejecución.2)
Esto es
true
siobj1
es exactamente de tipoint
. Siobj1
deriva deint
, la condición if seráfalse
.3)
Esto es
true
siobj1
es 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 deo
esDog
, noAnimal
. Sin embargo, puede hacer que esto funcione si usa elIsAssignableFrom
método de laType
clase.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
is
palabra clave. Por lo tanto, si este es el comportamiento que desea, debe usar lais
palabra clave, que es más legible y más eficiente.Sin embargo, en la mayoría de los casos, la
is
palabra 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
is
operador, y si deo
hecho es unAnimal
, lo haremos verificar nuevamente para validar el lanzamiento.Es más eficiente hacer esto en su lugar:
El
as
operador 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
o
habrá 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 unInvalidCastException
en 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
o
serloAnimal
cada vez, pero esto no es obvio en el constructor, dondeas
se usa el elenco. No es obvio hasta que llegue alInteract
método, dondeanimal
se 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
as
y 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 variableo
es 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
switch
En este caso, es aconsejable declaración con coincidencia de patrones .if (obj1 is int integerValue) { integerValue++; }
Tenía una
Type
propiedad para comparar y no podía usaris
(me gustamy_type is _BaseTypetoLookFor
), pero podía usar estos:Tenga en cuenta que
IsInstanceOfType
yIsAssignableFrom
regresetrue
al comparar los mismos tipos, donde IsSubClassOf regresaráfalse
. YIsSubclassOf
no 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
typeof
no está definido en un espacio de nombres, es una palabra clave.System.IO
No 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
DateTime
no 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 aDateTime
en Win7 es de 15 ms.