Pregunta

En el libro Learning C# de Jesse Liberty, dice: "Los objetos de un tipo se pueden convertir en objetos de otro tipo.A esto se le llama casting."

Si investiga el IL generado a partir del código siguiente, podrá ver claramente que la tarea convertida no hace lo mismo que la tarea convertida.En el primero, puede ver cómo se produce el boxeo/unboxing;en este último puedes ver una llamada a un método de conversión.

Sé que al final puede ser solo una diferencia semántica tonta, pero es solo otra palabra para conversión.No quiero ser sarcástico, pero no me interesa el presentimiento de nadie sobre esto: ¡las opiniones no cuentan aquí!¿Alguien puede señalar una referencia definitiva que confirme o niegue si emitir y convertir son lo mismo?

    object x;
    int y;

    x = 4;

    y = ( int )x;

    y = Convert.ToInt32( x );

Gracias

rp

Nota agregada después del comentario de Matt sobre explícito/implícito:

No creo que implícita/explícita sea la diferencia.En el código que publiqué, el cambio es explícito en ambos casos.Una conversión implícita es lo que ocurre cuando asignas un short a un int.

Nota para Sklivvz:

Quería confirmación de que mi sospecha sobre la laxitud del lenguaje de Jesse Liberty (por lo demás normalmente lúcido y claro) era correcta.Pensé que Jesse Liberty estaba siendo un poco relajado con su lenguaje.Entiendo que la conversión se enruta en la jerarquía de objetos, es decir, no se puede convertir de un número entero a una cadena, pero se puede convertir desde una excepción personalizada derivada de System.Exception a System.Exception.

Sin embargo, es interesante que cuando intentas convertir un int a una cadena, el compilador te dice que no pudo "convertir" el valor.¡Quizás Jesse tenga más razón de lo que pensaba!

¿Fue útil?

Solución

La respuesta simple es: depende.

Para los tipos de valor, la conversión implicará convertirlo genuinamente a un tipo diferente. Por ejemplo:

float f = 1.5f;
int i = (int) f; // Conversion

Cuando la expresión de conversión desempaqueta, el resultado (suponiendo que funcione) es generalmente solo una copia de lo que estaba en el cuadro, con el mismo tipo. Sin embargo, hay excepciones: puede desempaquetar de un int en caja a una enumeración (con un tipo subyacente de int) y viceversa; Del mismo modo, puede desempaquetar de un int en caja a un Nullable < int > ;.

Cuando la expresión de conversión es de un tipo de referencia a otro y no se trata de una conversión definida por el usuario, no hay conversión en lo que respecta al objeto en sí, ¡solo el tipo de referencia quot; cambia " - y esa es realmente solo la forma en que se considera el valor, en lugar de la referencia en sí (que serán los mismos bits que antes). Por ejemplo:

object o = "hello";
string x = (string) o; // No data is "converted"; x and o refer to the same object

Cuando las conversiones definidas por el usuario se involucran, esto generalmente implica devolver un objeto / valor diferente. Por ejemplo, podría definir una conversión a cadena para su propio tipo, y  esto ciertamente no sería la misma información que su propio objeto. (Puede ser una cadena existente a la que se hace referencia desde su objeto, por supuesto). En mi experiencia, las conversiones definidas por el usuario generalmente existen entre tipos de valor en lugar de tipos de referencia, por lo que esto rara vez es un problema.

Todos estos cuentan como conversiones en términos de la especificación, pero no todos cuentan como convertir un objeto en un objeto de un tipo diferente. Sospecho que este es un caso de Jesse Liberty que no tiene terminología: lo noté en la Programación C # 3.0, que acabo de leer.

¿Eso cubre todo?

Otros consejos

¡Absolutamente no!

Convert intenta obtener un Int32 a través de " cualquier medio posible " ;. Cast no hace nada por el estilo. Con Cast, le está diciendo al compilador que trate el objeto como Int, sin conversión.

Siempre debe usar cast cuando sepa (por diseño) que el objeto es Int32 u otra clase que tiene un operador de conversión a Int32 (como flotante, por ejemplo).

Convert debe usarse con String o con otras clases.

Prueba esto

static void Main(string[] args)
{
    long l = long.MaxValue;

    Console.WriteLine(l);

    byte b = (byte) l;

    Console.WriteLine(b);

    b = Convert.ToByte(l);

    Console.WriteLine(b);

}

Resultado:

  

9223372036854775807

     

255

     

Excepción no controlada:

     

System.OverflowException: el valor es   mayor que Byte.MaxValue o menor   que Byte.MinValue en   System.Convert.ToByte (valor Int64)   [0x00000] en Test.Main   (System.String [] args) [0x00019] en   /home/marco/develop/test/Exceptions.cs:15

La mejor explicación que he visto se puede ver a continuación, seguida de un enlace a la fuente:

" ... La verdad es un poco más compleja que eso. .NET proporciona tres métodos para llegar del punto A al punto B, por así decirlo.

Primero, está el elenco implícito. Este es el elenco que no requiere que haga algo más que una tarea:

int i = 5;
double d = i;

También se denominan " ampliando las conversiones " y .NET te permite realizarlos sin ningún operador de lanzamiento porque nunca podría perder ninguno información que lo hace: el posible rango de valores válidos de un doble abarca el rango de valores válidos para un int y luego algunos, por lo que nunca vas a hacer esta tarea y luego descubres a tu horror de que el tiempo de ejecución haya reducido algunos dígitos de su valor int. por tipos de referencia, la regla detrás de un elenco implícito es que el elenco nunca podría lanzar una InvalidCastException: está claro para el compilador que el reparto siempre es válido.

Puede crear nuevos operadores de conversión implícitos para sus propios tipos (que significa que puedes hacer lanzamientos implícitos que rompen todas las reglas, si eres estúpido al respecto). La regla básica es que un implícito el elenco nunca puede incluir la posibilidad de perder información en el transición.

Tenga en cuenta que la representación subyacente cambió en este conversión: un doble se representa completamente diferente de un int.

El segundo tipo de conversión es una conversión explícita. Un reparto explícito es requerido siempre que exista la posibilidad de perder información, o existe la posibilidad de que el elenco no sea válido y, por lo tanto, arroje una InvalidCastException:

double d = 1.5;
int i = (int)d;

Aquí obviamente va a perder información: seré 1 después del emitidos, por lo que el 0.5 se pierde. Esto también se conoce como & Quot; estrechando & Quot; conversión, y el compilador requiere que incluya una conversión explícita (int) para indicar que sí, usted sabe que la información puede perderse, pero no te importa.

Del mismo modo, con los tipos de referencia, el compilador requiere conversiones explícitas en situaciones en las que el reparto puede no ser válido en tiempo de ejecución, como una señal eso sí, sabes que hay un riesgo, pero sabes lo que estás haciendo.

El tercer tipo de conversión es aquel que implica un cambio tan radical en representación de que los diseñadores no proporcionaron ni siquiera una información explícita cast: te hacen llamar a un método para hacer la conversión:

string s = "15";
int i = Convert.ToInt32(s);

Tenga en cuenta que no hay nada que requiera absolutamente una llamada a un método aquí. Los lanzamientos implícitos y explícitos también son llamadas a métodos (así es como se hacen tu propio). Los diseñadores podrían haber creado fácilmente un documento explícito operador de conversión que convirtió una cadena en un int. El requisito de que llamar a un método es una elección estilística en lugar de una fundamental requisito del idioma.

El razonamiento estilístico es más o menos así: String-to-int es un Conversión complicada con muchas oportunidades para que todo funcione horriblemente mal:

string s = "The quick brown fox";
int i = Convert.ToInt32(s);

Como tal, la llamada al método le proporciona documentación para leer, y una amplia insinúa que esto es algo más que un lanzamiento rápido.

Al diseñar sus propios tipos (particularmente sus propios tipos de valor), usted puede decidir crear operadores de conversión y funciones de conversión. Las líneas dividiendo " conversión implícita " ;, " conversión explícita " ;, y " función de conversión " el territorio es un poco borroso, por lo que diferentes personas pueden hacer diferentes decisiones sobre qué debería ser qué. Solo trata de tener en cuenta pérdida de información y posibilidad de excepciones y datos no válidos, y eso debería ayudarlo a decidir. "

  • Bruce Wood, 16 de noviembre de 2005

http://bytes.com/forum/post1068532-4.html

La conversión implica referencias

List<int> myList = new List<int>();
//up-cast
IEnumerable<int> myEnumerable = (IEnumerable<int>) myList;
//down-cast
List<int> myOtherList = (List<int>) myEnumerable;

Observe que las operaciones en myList, como agregar un elemento, se reflejan en myEnumerable y myOtherList. Esto se debe a que todas son referencias (de diferentes tipos) a la misma instancia.

La fundición es segura. La conversión descendente puede generar errores de tiempo de ejecución si el programador ha cometido un error en el tipo. La transmisión segura está más allá del alcance de esta respuesta.

La conversión implica instancias

List<int> myList = new List<int>();
int[] myArray = myList.ToArray();

myList se usa para producir myArray. Esta es una conversión no destructiva (myList funciona perfectamente bien después de esta operación). Observe también que las operaciones contra myList, como agregar un elemento, no se reflejan en myArray. Esto se debe a que son instancias completamente separadas.

decimal w = 1.1m;
int x = (int)w;

Hay operaciones que utilizan la sintaxis de conversión en C # que son en realidad conversiones .

Dejando a un lado la semántica, una prueba rápida muestra que son ¡NO equivalente!
Hacen la tarea de manera diferente (o tal vez hacen tareas diferentes).

x=-2.5 (int)x=-2 Convert.ToInt32(x)=-2
x=-1.5 (int)x=-1 Convert.ToInt32(x)=-2
x=-0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 0.5 (int)x= 0 Convert.ToInt32(x)= 0
x= 1.5 (int)x= 1 Convert.ToInt32(x)= 2
x= 2.5 (int)x= 2 Convert.ToInt32(x)= 2

Observe la x=-1.5 y x=1.5 casos.

Un elenco le dice al compilador / interpertor que el objeto es de ese tipo (o tiene un tipo de base / interfaz de ese tipo). Es algo bastante rápido de hacer en comparación con un convertidor donde ya no es el compilador / interpertor el que hace el trabajo, sino una función actualling que analiza una cadena y hace cálculos matemáticos para convertir a un número.

Lanzar siempre significa cambiar el tipo de datos de un objeto. Esto se puede hacer, por ejemplo, convirtiendo un valor flotante en un valor entero o reinterpretando los bits. Usualmente es una operación compatible con el idioma (léase: compatible con el compilador).

El término " convertir " a veces se usa para transmitir, pero generalmente lo hace alguna biblioteca o su propio código y no necesariamente da como resultado la conversión. Por ejemplo, si tiene un valor de peso imperial y lo convierte en peso métrico, puede permanecer el mismo tipo de datos (por ejemplo, flotante), pero puede convertirse en un número diferente. Otro ejemplo típico es la conversión de grados a radianes.

En una forma de hablar independiente del lenguaje / marco, la conversión de un tipo o clase a otra se conoce como conversión . Esto también es cierto para .NET, como muestran sus primeras cuatro líneas:

object x;
int y;

x = 4;

y = ( int )x;

Los lenguajes C y C (como C #) usan la sintaxis (newtype)somevar para la conversión. En VB.NET, por ejemplo, hay funciones incorporadas explícitas para esto. La última línea se escribiría como:

y = CInt(x)

O, para tipos más complejos:

y = CType(x, newtype)

Donde 'C' obviamente es la abreviatura de 'elenco'.

.NET también tiene la función Convert(), sin embargo. Esta no es una función de lenguaje incorporada (a diferencia de las dos anteriores), sino más bien una del marco. Esto se vuelve más claro cuando usas un lenguaje que no necesariamente se usa junto con .NET: todavía es muy probable que tengan sus propios medios de conversión, pero es .NET el que agrega y.

Como dice Matt, la diferencia de comportamiento es que x es más explícito. En lugar de simplemente decirle al compilador que trate a <=> como un equivalente entero de <=>, le está diciendo específicamente que modifique <=> de tal manera que sea adecuada para la clase entera, luego asignar el resultado a <=>.

En su caso particular, el casting hace lo que se llama 'unboxing', mientras que <=> realmente obtendrá el valor entero. El resultado será el mismo, pero hay diferencias sutiles mejor explicado por Keith .

De acuerdo con la Tabla 1-7 titulada " Métodos para conversión explícita " en la página 55 en el Capítulo 1, Lección 4 del Kit de entrenamiento de MCTS a su propio ritmo (Examen 70-536): Microsoft & # 174; .NET Framework 2.0 & # 8212; Application Development Foundation , ciertamente hay una diferencia entre ellos.

System.Convert es independiente del idioma y convierte " entre los tipos que implementan la interfaz System.IConvertible . "

(tipo) operador de conversión es una función de lenguaje específica de C # que convierte " entre tipos que definen operadores de conversión . "

Además, al implementar conversiones personalizadas, los consejos difieren entre ellos.

Según la sección titulada Cómo implementar la conversión en tipos personalizados en las páginas 56-57 en la lección citada anteriormente, los operadores de conversión (conversión) están destinados a simplificar las conversiones entre tipos numéricos, mientras que Convert () permite conversiones culturales específicas .

  

La técnica que elija dependerá del tipo de conversión que desee realizar:

     
      
  • Definir operadores de conversión para simplificar el estrechamiento y la ampliación   conversiones entre tipos numéricos.

  •   
  • Implemente System.IConvertible para permitir la conversión a través de   Sistema.Convertir. Use esta técnica para habilitar conversiones específicas de la cultura.

  •   
  • ...

  •   

Debería ser más claro ahora que, dado que el operador de conversión de conversión se implementa por separado de la interfaz IConvertible, Convert () no es necesariamente simplemente otro nombre para la conversión. (Pero puedo imaginar dónde una implementación puede referirse a la otra para garantizar la coherencia).

No olvide los otros métodos de conversión y conversión de variables: como, Parse, TryParse así como la conversión implícita entre tipos de datos compatibles.

Este sitio tiene una buena muestra de cuáles son los resultados para la mayoría de los métodos: C # Boxing and Unboxing

Entonces, dadas estas variables de muestra:

int i = 3, x;
long l;
string s = "5";

Básicamente puede tener una conversión implícita, entre dos tipos compatibles:

l = i;

Conversión explícita utilizando unboxing o la palabra clave como :

s = (string)i;
//or
s = i as string;

Conversiones explícitas utilizando métodos de System.Convert:

i = System.Convert.ToInt32(s);

Conversiones explícitas utilizando métodos de un tipo de datos definido:

i = int.Parse(s);
i = int.TryParse(s, x);

Conversiones explícitas utilizando métodos de una instancia de una variable:

s = i.ToString();

Creo que casting es simplemente una forma de hacer asignaciones entre dos tipos compatibles.

Convertir es si necesita copiar explícitamente un valor de un tipo incompatible a otro, y no puede confiar en coerción maligna .

Alguna buena información también sobre MSDN: Conversiones de fundición y tipo

Casting es esencialmente solo decirle al tiempo de ejecución que " pretender " El objeto es el nuevo tipo. En realidad, no convierte ni cambia el objeto de ninguna manera.

Convert, sin embargo, realizará operaciones para convertir un tipo en otro.

Como ejemplo:

char caster = '5';
Console.WriteLine((int)caster);

El resultado de esas declaraciones será 53, porque todo lo que hizo el tiempo de ejecución fue mirar el patrón de bits y tratarlo como un int. Lo que terminas obteniendo es el valor ASCII del personaje 5, en lugar del número 5.

Sin embargo, si usa Convert.ToInt32 (caster), obtendrá 5 porque en realidad lee la cadena y la modifica correctamente. (Esencialmente sabe que el valor ASCII 53 es realmente el valor entero 5.)

La diferencia es si la conversión es implícita o explícita. El primero allí es un elenco, el segundo es una llamada más explícita a una función que convierte. Probablemente hagan lo mismo de diferentes maneras.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top