tipos para name keywords importantes etiquetas etiqueta ejemplos c# .net casting type-systems as-operator

c# - para - seo tags html



¿Por qué no puedo usar la palabra clave as para una estructura? (6)

Definí la siguiente estructura:

public struct Call { public SourceFile caller; public SourceFile callee; public Call(SourceFile caller, SourceFile callee) { this.caller = caller; this.callee = callee; } }

Más tarde, lo asigno a la propiedad Tag de otro objeto:

line.Tag = new Call(sf1, sf2);

Pero cuando trato de recuperar la propiedad Tag como tal,

Call call = line.Tag as Call;

Visual Studio da el siguiente error en tiempo de compilación:

El operador debe ser usado dentro de un tipo de referencia o tipo de nullas

¿Cuál es el significado de eso? ¿Y cómo puedo solucionarlo?


¿Cuál es el significado? Como se dijo, las estructuras son tipos de valor.

¿Cómo puedo resolverlo?

Call call = line.Tag;


Algunas de las respuestas existentes no son del todo correctas. No puede usar tipos no anulables con as , porque el resultado de as es el valor nulo del tipo si el primer operando no es realmente del tipo adecuado.

Sin embargo, puede usar as con los tipos de valor ... si son anulables:

int a = 10; object o = a; int? x = o as int?; // x is a Nullable<int> with value 10 long? y = o as long?; // y is a Nullable<long> with the null value

Para que puedas usar:

Call? call = line.Tag as Call?;

Entonces puedes usarlo como:

if (call != null) { // Do stuff with call.Value }

Dos advertencias sin embargo:

  • En mi experiencia, esto es más lento que solo usarlo is seguido por un lanzamiento
  • Deberías reconsiderar seriamente tu tipo de Call actual:
    • Está exponiendo campos públicos, lo que generalmente es una mala encapsulación.
    • Es un tipo de valor mutable, que es casi seguramente un error.

Le sugeriría encarecidamente que lo convierta en una clase, en cuyo punto este problema desaparece de todos modos.

Otro pensamiento: si la etiqueta siempre debería ser una Call , entonces es mejor lanzarla:

Call call = (Call) line.Tag;

De esa manera, si los datos no coinciden con sus expectativas (es decir, hay algún error que indica que la Tag no es una Call ), podrá descubrirlo pronto, en lugar de hacerlo después de haber realizado algún otro trabajo. Tenga en cuenta que esta conversión se comportará de manera diferente dependiendo de si la Call es una estructura o una clase, si la Tag es nula: puede convertir un valor nulo a una variable de un tipo de referencia (o un tipo de valor que puede contener nulos), pero no a un no tipo de valor anulable.


De la especificación de C #

§7.10.11 El operador as se usa para convertir explícitamente un valor a un tipo de referencia o tipo anulable dado. A diferencia de una expresión de conversión (§7.7.6), el operador as nunca lanza una excepción. En cambio, si la conversión indicada no es posible, el valor resultante es nulo .

Las referencias y los tipos anulables pueden ser nulos. Los stucts son tipos de valor por lo que no pueden ser nulos.


Es una limitación de C #. Si el tipo fuera un tipo de referencia, entonces si la conversión fallara, simplemente devolvería ''nulo'', pero como es un tipo de valor, no sabe qué devolver cuando falla la conversión.

Debe reemplazar su uso de como con dos: ''es'' y ''como''

if (line.Tag is Call) { call = (Call)line.Tag; } else { // Do whatever you would do if as returned null. }


Una estructura es un tipo de valor, por lo que no se puede utilizar con el operador as . El operador as debe poder asignar un valor nulo si la conversión falla. Esto solo es posible con un tipo de referencia o un tipo de valor anulable.

Hay un par de maneras de resolver esto, pero lo mejor es cambiar el tipo de Call de una estructura a una clase. Básicamente, esto cambiará su tipo de un tipo de valor a un tipo de referencia, lo que le permite al operador as asignarle un valor nulo si la conversión falla.

Para obtener más información sobre los tipos de valor en comparación con los tipos de referencia, this es un artículo decente. Además, echa un vistazo a MSDN:


Call? call = line.Tag as Call?;