variable type sirve que para ejemplos ejemplo c#

sirve - typeof expression c#



Comprobación de tipo: typeof, GetType, o es? (14)

Se utiliza para obtener el objeto System.Type para un tipo. Una expresión typeof toma la siguiente forma:

System.Type type = typeof(int); Example: public class ExampleClass { public int sampleMember; public void SampleMethod() {} static void Main() { Type t = typeof(ExampleClass); // Alternatively, you could use // ExampleClass obj = new ExampleClass(); // Type t = obj.GetType(); Console.WriteLine("Methods:"); System.Reflection.MethodInfo[] methodInfo = t.GetMethods(); foreach (System.Reflection.MethodInfo mInfo in methodInfo) Console.WriteLine(mInfo.ToString()); Console.WriteLine("Members:"); System.Reflection.MemberInfo[] memberInfo = t.GetMembers(); foreach (System.Reflection.MemberInfo mInfo in memberInfo) Console.WriteLine(mInfo.ToString()); } } /* Output: Methods: Void SampleMethod() System.String ToString() Boolean Equals(System.Object) Int32 GetHashCode() System.Type GetType() Members: Void SampleMethod() System.String ToString() Boolean Equals(System.Object) Int32 GetHashCode() System.Type GetType() Void .ctor() Int32 sampleMember */

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.

class GetTypeTest { static void Main() { int radius = 3; Console.WriteLine("Area = {0}", radius * radius * Math.PI); Console.WriteLine("The type is {0}", (radius * radius * Math.PI).GetType() ); } } /* Output: Area = 28.2743338823081 The type is System.Double */

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 esté perdiendo? ¿Cuál es el mejor para usar, o es la preferencia personal?


Creo que la última también analiza la herencia (por ejemplo, Dog is Animal == true), que es mejor en la mayoría de los casos.


Depende de lo que esté haciendo. Si necesito un valor bool (por ejemplo, para determinar si lanzaré a un int), usaré is . Si realmente necesito el tipo por alguna razón (por ejemplo, para pasar a otro método) GetType() .


El último es más limpio, más obvio y también verifica los subtipos. Los otros no comprueban el polimorfismo.


Prueba de rendimiento typeof () vs GetType ():

using System; namespace ConsoleApplication1 { class Program { enum TestEnum { E1, E2, E3 } static void Main(string[] args) { { var start = DateTime.UtcNow; for (var i = 0; i < 1000000000; i++) Test1(TestEnum.E2); Console.WriteLine(DateTime.UtcNow - start); } { var start = DateTime.UtcNow; for (var i = 0; i < 1000000000; i++) Test2(TestEnum.E2); Console.WriteLine(DateTime.UtcNow - start); } Console.ReadLine(); } static Type Test1<T>(T value) => typeof(T); static Type Test2(object value) => value.GetType(); } }

Resultados en el modo de depuración:

00:00:08.4096636 00:00:10.8570657

Resultados en modo de lanzamiento:

00:00:02.3799048 00:00:07.1797128


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.


Si está utilizando C # 7, es hora de actualizar la excelente respuesta de Andrew Hare. La coincidencia de patrones ha introducido un método abreviado agradable que nos da una variable escrita en el contexto de la sentencia if, sin requerir una declaración / conversión y verificación por separado:

if (obj1 is int integerValue) { integerValue++; }

Esto parece bastante decepcionante para un elenco como este, pero realmente brilla cuando tienes muchos tipos posibles en tu rutina. La siguiente es la vieja forma de evitar lanzar dos veces:

Button button = obj1 as Button; if (button != null) { // do stuff... return; } TextBox text = obj1 as TextBox; if (text != null) { // do stuff... return; } Label label = obj1 as Label; if (label != null) { // do stuff... return; } // ... and so on

Trabajar alrededor de reducir este código tanto como sea posible, así como evitar las repeticiones duplicadas del mismo objeto siempre me ha molestado. Lo anterior está muy bien comprimido con un patrón que coincide con lo siguiente:

switch (obj1) { case Button button: // do stuff... break; case TextBox text: // do stuff... break; case Label label: // do stuff... break; // and so on... }

EDITAR: Se actualizó el nuevo método más largo para usar un interruptor según el comentario de Palec.


Tenía una propiedad de Type con la que comparar y no podía usar (como my_type is _BaseTypetoLookFor ), pero podría usar estos:

base_type.IsInstanceOfType(derived_object); base_type.IsAssignableFrom(derived_type); derived_type.IsSubClassOf(base_type);

Observe que IsInstanceOfType y IsAssignableFrom devuelven true cuando se comparan los mismos tipos, donde IsSubClassOf devolverá false . E IsSubclassOf no funciona en las interfaces, donde lo hacen los otros dos. (Ver también esta pregunta y respuesta ).

public class Animal {} public interface ITrainable {} public class Dog : Animal, ITrainable{} Animal dog = new Dog(); typeof(Animal).IsInstanceOfType(dog); // true typeof(Dog).IsInstanceOfType(dog); // true typeof(ITrainable).IsInstanceOfType(dog); // true typeof(Animal).IsAssignableFrom(dog.GetType()); // true typeof(Dog).IsAssignableFrom(dog.GetType()); // true typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true dog.GetType().IsSubclassOf(typeof(Animal)); // true dog.GetType().IsSubclassOf(typeof(Dog)); // false dog.GetType().IsSubclassOf(typeof(ITrainable)); // false


Todos son diferentes.

  • typeof toma un nombre de tipo (que especifica en tiempo de compilación).
  • GetType obtiene el tipo de tiempo de ejecución de una instancia.
  • devuelve true si una instancia está en el árbol de herencia.

Ejemplo

class Animal { } class Dog : Animal { } void PrintTypes(Animal a) { Console.WriteLine(a.GetType() == typeof(Animal)); // false Console.WriteLine(a is Animal); // true Console.WriteLine(a.GetType() == typeof(Dog)); // true Console.WriteLine(a is Dog); // true } Dog spot = new Dog(); PrintTypes(spot);

¿Qué pasa con typeof(T) ? ¿También se resuelve en tiempo de compilación?

Sí. T es siempre lo que el tipo de expresión es. Recuerde, un método genérico es básicamente un montón de métodos con el tipo apropiado. Ejemplo:

string Foo<T>(T parameter) { return typeof(T).Name; } Animal probably_a_dog = new Dog(); Dog definitely_a_dog = new Dog(); Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal" Foo<Animal>(probably_a_dog); // this is exactly the same as above Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal. Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog" Foo<Dog>(definitely_a_dog); // this is exactly the same as above. Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal". Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"


Utilice typeof cuando desee obtener el tipo en tiempo de compilación . Utilice GetType cuando desee obtener el tipo en el momento de la ejecución . Rara vez hay casos que usar, como lo es un cast 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); que es usar as .

Foo foo = obj as Foo; if (foo != null) // your code here

Esto solo usa un elenco mientras que este enfoque:

if (obj is Foo) Foo foo = (Foo)obj;

requiere dos .


Yo prefiero es

Dicho esto, si estás usando es probable que no estés usando la herencia correctamente.

Supongamos que Persona: Entidad, y ese Animal: Entidad. Feed es un método virtual en Entity (para hacer feliz a Neil)

class Person { // A Person should be able to Feed // another Entity, but they way he feeds // each is different public override void Feed( Entity e ) { if( e is Person ) { // feed me } else if( e is Animal ) { // ruff } } }

Más bien

class Person { public override void Feed( Person p ) { // feed the person } public override void Feed( Animal a ) { // feed the animal } }


1.

Type t = typeof(obj1); if (t == typeof(int))

Esto es ilegal, porque typeof solo funciona en tipos, no en variables. Supongo que obj1 es una variable. Entonces, de esta manera, typeof es estático, y hace su trabajo en tiempo de compilación en lugar de en tiempo de ejecución.

2.

if (obj1.GetType() == typeof(int))

Esto es cierto si obj1 es exactamente de tipo int. Si obj1 se deriva de int, la condición if será falsa.

3.

if (obj1 is int)

Esto es cierto si obj1 es un int, o si se deriva de una clase llamada int, o si implementa una interfaz llamada int.


Type t = typeof(obj1); if (t == typeof(int)) // Some code here

Esto es un error. El operador typeof en C # solo puede tomar nombres de tipo, no objetos.

if (obj1.GetType() == typeof(int)) // Some code here

Esto funcionará, pero tal vez no como usted esperaría. Para los tipos de valor, como se muestra aquí, es aceptable, pero para los tipos de referencia, solo devolvería verdadero si el tipo fuera exactamente el mismo tipo, no otra cosa en la jerarquía de herencia. Por ejemplo:

class Animal{} class Dog : Animal{} static void Foo(){ object o = new Dog(); if(o.GetType() == typeof(Animal)) Console.WriteLine("o is an animal"); Console.WriteLine("o is something else"); }

Esto imprimiría "o is something else" , porque el tipo de o es Dog , no Animal . Sin embargo, puede hacer que esto funcione si usa el método IsAssignableFrom de la clase Type .

if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type Console.WriteLine("o is an animal");

Sin embargo, esta técnica todavía deja un gran problema. Si su variable es nula, la llamada a GetType() lanzará una NullReferenceException. Así que para que funcione correctamente, harías:

if(o != null && typeof(Animal).IsAssignableFrom(o.GetType())) Console.WriteLine("o is an animal");

Con esto, tienes un comportamiento equivalente de la palabra clave is . Por lo tanto, si este es el comportamiento que desea, debe usar la palabra clave is , que es más legible y más eficiente.

if(o is Animal) Console.WriteLine("o is an animal");

Sin embargo, en la mayoría de los casos, la palabra clave is todavía no es lo que realmente quiere, porque generalmente no es suficiente solo para saber que un objeto es de cierto tipo. Por lo general, realmente desea utilizar ese objeto como una instancia de ese tipo, lo que también requiere su conversión. Y entonces puedes encontrarte escribiendo un código como este:

if(o is Animal) ((Animal)o).Speak();

Pero eso hace que el CLR verifique el tipo de objeto hasta dos veces. Lo comprobará una vez para satisfacer el operador, y si o es un Animal , lo hacemos nuevamente para validar el modelo.

Es más eficiente hacer esto en su lugar:

Animal a = o as Animal; if(a != null) a.Speak();

El operador as es un reparto que no lanzará una excepción si falla, en lugar de devolver un 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 hace excepciones, algunas personas lo consideran un elenco "seguro" y lo usan exclusivamente, evitando los lanzamientos regulares. Esto conduce a errores como este:

(o as Animal).Speak();

En este caso, el desarrollador asume claramente que o siempre será un Animal , y siempre que su suposición sea correcta, todo funciona bien. Pero si están equivocados, entonces lo que terminan aquí es una NullReferenceException . Con un reparto regular, habrían obtenido una InvalidCastException lugar, lo que habría identificado más correctamente el problema.

A veces, este error puede ser difícil de encontrar:

class Foo{ readonly Animal animal; public Foo(object o){ animal = o as Animal; } public void Interact(){ animal.Speak(); } }

Este es otro caso en el que el desarrollador claramente espera que sea un Animal cada vez, pero esto no es obvio en el constructor, donde se usa el modelo colado. No es obvio hasta que llegue al método Interact , donde se espera que el campo animal sea ​​asignado de manera positiva. En este caso, no solo terminará con una excepción engañosa, sino que no se lanzará sino hasta 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, su uso is .

  • Si necesita tratar un objeto como una instancia de un determinado tipo, pero no está seguro de que el objeto sea de ese tipo, utilice as y compruebe si hay un null .

  • Si necesita tratar un objeto como una instancia de un determinado tipo, y se supone que el objeto es de ese tipo, use una conversión regular.


if (c is UserControl) c.Enabled = enable;