2009-05-20 13 views
6

C# acepta lo siguiente:no se puede convertir el tipo 'cadena' a 'int?' a través de una conversión de referencia, la conversión de boxeo, la conversión unboxing, la conversión de envolver o de conversión de tipo nulo

object o = "hello"; 
int? i = o as int?; 

if (i == null) { 
    // o was not a boxed int 
} 
else { 
    // Can use i.Value to recover the original boxed value 
} 

Pero no

String o = "hello"; 
int? i = o as int?; 

if (i == null) { 
    // o was not a boxed int 
} 
else { 
    // Can use i.Value to recover the original boxed value 
} 

Me pregunto sobre el comportamiento de la palabra clave as en C#.

Al igual que en Java este fallaría:

Object test1 = "hello"; 
Integer test2 = (Integer) test1; 
String test3 = "hello"; 
Integer test4 = (Integer) test3; //compilation error 

Respuesta

17

el compilador sabe que una cadena no puede ser nunca un int? por lo que le dice eso. Eso no significa que int? no sea útil. Su caso de intento de uso está lejos de ser el caso normal. La normal es "Quiero representar un número entero y la posibilidad de que el valor esté perdido/desconocido". Para eso, int? funciona extremadamente bien.

¿Por qué querrías esperar el código original para trabajar? ¿Por qué sería útil?

Tenga en cuenta que puede uso as con tipos anulables, por unboxing:

object o = "hello"; 
int? i = o as int?; 

if (i == null) 
{ 
    // o was not a boxed int 
} 
else 
{ 
    // Can use i.Value to recover the original boxed value 
} 

EDIT: Después de haber visto a tu comentario, no utiliza as para analizar las cosas. Es posible que desee utilizar int.TryParse:

string text = "123": 
int value; 
if (int.TryParse(text, out value)) 
{ 
    Console.WriteLine("Parsed successfully: {0}", value); 
} 
else 
{ 
    Console.WriteLine("Unable to parse text as an integer"); 
} 

Si está seguro de la cadena está destinado a ser un número entero (es decir, es un error de otro tipo) a continuación, puedes utilizar int.Parse:

int value = int.Parse(text); 

que la voluntad lanzar una excepción si el análisis falla.

Tenga en cuenta también que estos dos métodos le permiten especificar un proveedor de formato (generalmente una información cultural) que le permite expresar cómo se expresan los números en ese formato (por ejemplo, separadores de miles).

EDITAR: En respuesta a su nueva pregunta, el compilador evita esto porque sabe que una cadena no puede posiblemente sea un recuadro int - la conversión nunca tendrá éxito.Cuando solo sabe que el valor original es un objeto, podría tener éxito.

Por ejemplo, supongamos que te dije: "Aquí hay una forma: ¿es un cuadrado?" Esa es una pregunta sensata. Es razonable preguntar: no se puede decir sin mirar la forma.

Si, sin embargo, dije: "Aquí hay un triángulo: ¿es un cuadrado?" Entonces tendrías el derecho razonable de reírte en mi cara, ya que un triángulo no puede ser un cuadrado, la pregunta no tiene sentido.

+0

porque se está intentando asignar un valor de cadena a un entero. el signo de interrogación solo permite que int contenga un valor nulo, no cambia el hecho de que es un int. – kscott

+0

Juan: No usa un molde o "como" para convertir cadenas y otros tipos. No hay una conversión implícita o explícita disponible; debe usar un método de análisis sintáctico. Vea la segunda mitad de mi respuesta para más detalles y un ejemplo. –

+0

No, nunca habría esperado que un operador de conversión intentara realizar el análisis sintáctico. Vaya, parece que leí mal tu pregunta editada, pensé que dijiste que * estabas * intentando encontrar la manera de hacer la conversión.Sin embargo, dejaré la información adicional para futuros lectores. –

2

int? significa un tipo entero numerable, no un int que podría contener cualquier otro tipo de variable.

Si desea un tipo de variable que podría contener un int o una cadena, tendría que usar un objeto, o una cadena, supongo, y luego vivir una vida llena de conversión de tipo. Sin embargo, no sé por qué querrías hacer eso.

int? le permite almacenar cualquier valor entero, o un valor nulo. Lo cual es útil cuando la respuesta a la pregunta "¿Cuántas órdenes ha colocado esta persona?" Es legítimamente "No sé" en lugar de un número de órdenes, o cero, que sería "Sé con certeza que esta persona nunca puse una orden".

0

pero puede verificar el valor de nulo y establecerlo en nulo.

int? blah; 
if (blah == null) 
{} 
0

int? es un entero que puede contener nulos, no tiene nada que ver con el casting y la palabra clave as. "Cadena" es un objeto tipo cadena, que no es convertible a un int (nulable o no).

El que la palabra clave es prácticamente la misma que la fundición a soportes excepto que no devolverá un error, se establece el objeto a null:

int i = 1; 

object o = i; //boxing 

int j = (int)o; //unboxing 

Este primer ejemplo funciona como el objeto asignado a O es un En t.

Consideremos ahora:

string i = "MyString"; 

object o = MyString; 

int j = (int)o //unboxing raises exception 

int j = o as int; //raises compilation Error as int is not nullable 
int? j = o as int?; /// o == null 

espero que eso ayuda a explicar la diferencia entre los dos conceptos.

Richard

+0

"int j = o as int" no genera una excepción: impide la compilación, porque no hay ningún valor para j en caso de que o no sea un recuadro int. –

+0

Lo siento, gracias por la corrección de Jon ... He actualizado la respuesta en consecuencia ... (con suerte) – Richbits

1

Deseo agregar más información.

Un otro caso, ¿por qué el reparto no es válido y el compilador genera un error de compilación es, que System.String se marca como sellada. Por lo tanto, el compilador sabe de qué tipos hereda el tipo System.String y a qué tipos puede convertir la cadena utilizando como operador.

Debido a la palabra clave sellada, el compilador sabe también que no puede Heredar del System.String para agregar funcionalidad o implementar algunas interfaces adicionales.

El código siguiente es un ejemplo y el compilador arrojará el siguiente error en la compilación

No se puede convertir tipo 'SealedClass' a 'ICastToInterface' a través de una conversión de referencia , la conversión de boxeo, conversión unboxing, envolver conversión o nula conversión de tipo

public class UnsealedClass { 
    // some code 
} 

public sealed class SealedClass { 
    // some code 
} 

public interface ICastToInterface { 
    // some code 
} 

public class Test { 

    public Test() { 
    UnsealedClass unsealedClass = new UnsealedClass(); 

    SealedClass sealedClass = new SealedClass(); 

    ICastToInterface unsealedCast = unsealedClass as ICastToInterface; // This works fine 

    ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed 
    } 
}