Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

224
Vistas
¿Hay alguna diferencia entre `x is int?` y `x is int` en C#?
class C<T> where T : struct { bool M1(object o) => o is T; bool M2(object o) => o is T?; }

Los dos métodos anteriores parecen comportarse por igual, tanto al pasar una referencia null como un valor T encuadrado. Sin embargo, el código MSIL generado es un poco diferente:

 .method private hidebysig instance bool M1(object o) cil managed { .maxstack 8 IL_0000: ldarg.1 IL_0001: isinst !T IL_0006: ldnull IL_0007: cgt.un IL_0009: ret }

contra

 .method private hidebysig instance bool M2(object o) cil managed { .maxstack 8 IL_0000: ldarg.1 IL_0001: isinst valuetype [mscorlib]System.Nullable`1<!T> IL_0006: ldnull IL_0007: cgt.un IL_0009: ret }

Como puede ver, la o is T? expresión en realidad realiza una verificación de tipo para el tipo Nullable<T> , a pesar de que CLR maneja especialmente los tipos que aceptan valores NULL para que C# represente la T? valor como referencia null (si T? no tiene valor) o valor T encuadrado. Parece imposible obtener un cuadro de Nullable<T> en C# puro o tal vez incluso en C++/CLI (ya que el tiempo de ejecución maneja el código de operación del box para admitir este cuadro " T? => T box / null ").

¿Me estoy perdiendo algo o o is T? es prácticamente equivalente a o is T en C#?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

De acuerdo con la especificación (énfasis mío), en E is T , los tipos de valor no anulables de T y los tipos anulables correspondientes se manejan de la misma manera:

7.10.10 El operador is

El operador is se usa para verificar dinámicamente si el tipo de tiempo de ejecución de un objeto es compatible con un tipo dado. El resultado de la operación E is T , donde E es una expresión y T es un tipo, es un valor booleano que indica si E se puede convertir correctamente al tipo T mediante una conversión de referencia, una conversión boxing o una conversión unboxing. La operación se evalúa de la siguiente manera, después de que los argumentos de tipo hayan sido sustituidos por todos los parámetros de tipo:

  • Si E es una función anónima, se produce un error en tiempo de compilación

  • Si E es un grupo de métodos o el literal nulo, o si el tipo de E es un tipo de referencia o un tipo que acepta valores NULL y el valor de E es nulo, el resultado es falso.

  • De lo contrario, represente D el tipo dinámico de E de la siguiente manera:

    • Si el tipo de E es un tipo de referencia, D es el tipo de tiempo de ejecución de la referencia de instancia de E .
    • Si el tipo de E es un tipo que acepta valores NULL, D es el tipo subyacente de ese tipo que acepta valores NULL.

    • Si el tipo de E es un tipo de valor que no acepta valores NULL, D es el tipo de E .

  • El resultado de la operación depende de D y T como sigue:

    • Si T es un tipo de referencia, el resultado es verdadero si D y T son del mismo tipo, si D es un tipo de referencia y existe una conversión de referencia implícita de D a T , o si D es un tipo de valor y una conversión boxing de D a T existe.
    • Si T es un tipo que acepta valores NULL, el resultado es verdadero si D es el tipo subyacente de T .
    • Si T es un tipo de valor que no acepta valores NULL, el resultado es verdadero si D y T son del mismo tipo .
    • De lo contrario, el resultado es falso.
over 4 years ago · Santiago Trujillo Denunciar

0

Considere este método genérico:

 static bool Is<T>(object arg) { return arg is T; }

La parte crucial de este método se compila en isinst !!T . Ahora esperaría que Is<int?>(arg) se comportara exactamente de la misma manera que arg is int? , ¿no? Para garantizar esta coherencia exacta, el compilador de C# debe emitir el mismo CIL en todos los casos y dejar que la carga de manejar los tipos anulables recaiga en el CLR.

El comportamiento de CLR se puede ver en el código fuente de coreclr en GitHub: IsInst , ObjIsInstanceOf . Como puede ver en la segunda función, si el tipo es una representación anulable del tipo de argumento, devuelve verdadero.

permitir que un objeto de tipo T se convierta en Nullable (tienen la misma representación)

Sí, el comportamiento actual de estas instrucciones es el mismo, entonces, ¿cambiar is T? to is T no hará ninguna diferencia (incluso para un argumento null ), pero para hacer frente a posibles cambios futuros en el CLR, el compilador de C# no puede tomar esa decisión (aunque la probabilidad de que cambie el comportamiento de isinst es cercana a cero).

Los tipos anulables son realmente maravillosos en .NET, especialmente debido a su manejo particular en CLR, a pesar de que no tienen una sintaxis especial en CIL (por compatibilidad). Realmente no hay una forma normal de encajonar un tipo anulable a su tipo real y no al subyacente, ya que generaría inconsistencias en las conversiones y comprobaciones (¿la referencia nula es igual a un tipo anulable encajonado nulo o no?). Sin embargo, puede engañar al CLR para que piense que le da un tipo anulable en caja (no es que deba hacerlo).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda