2010-07-21 7 views
5

considerar esta clase de prueba estática:¿Por qué C# lanza errores de conversión al intentar operaciones matemáticas en tipos enteros distintos de int?

public static class Test 
{ 
    public static ushort sum(ushort value1, ushort value2) 
    { 
     return value1 + value2 
    } 
} 

Esto hace que el siguiente error de compilación, con value1 + value2 subrayada en rojo:

No se puede convertir implícitamente el tipo 'int' a 'ushort'. Existe una conversión explícita (¿falta un elenco)?

¿Por qué?

+0

El compilador le pide que sea explícito sobre el hecho de que está haciendo una conversión de reducción, donde los datos pueden perderse. Si pasa en ushort.MaxValue y 1, ¿qué debería pasar? Esa es la pregunta que el compilador te recuerda que respondas. –

+0

@Dan: Lo que debería ocurrir es que el 'ushort' se desborde automáticamente, o arroje una excepción de desbordamiento si se usa la palabra clave' checked'. Si agrega dos valores 'int', no obtendrá el mismo error de compilación, aunque es posible el desbordamiento. –

+0

Mi opinión: el desbordamiento es algo que ocurre como resultado de una operación, no una asignación. En particular, puede desbordarse en medio de un cálculo complejo incluso si el resultado final estaría en el rango. Si se produce un desbordamiento, la operación matemática no ha funcionado como se esperaba, pero esto no ocurre al agregar dos ushorts en un sistema de 32 bits. Las matemáticas funcionaron bien, pero ahora debes decidir cómo interpretar el resultado. Si desea que se desborde ushort, entonces puede enviarlo a un ushort explícitamente. Esto podría suceder implícitamente, pero requerir un lanzamiento explícito es útil. –

Respuesta

7

Al igual que C y C++ antes, los enteros se amplían implícitamente cuando se usan con muchos operadores. En este caso, el resultado de agregar dos valores ushort es int.

Actualización:

Más información: http://msdn.microsoft.com/en-us/library/aa691330(v=VS.71).aspx

Creo que esto se agregó originalmente en C/C++ porque int era un tipo entero nativo (y sí, las operaciones fueron más rápidos en int s que en short s en arquitecturas de 32 bits). No estoy seguro de la razón fundamental de C#.

Te hace pensar en consideraciones de desbordamiento/truncamiento cuando lanzas. El desbordamiento accidental es más probable con los tipos enteros más pequeños.

+0

¿Así que se hace de esa manera porque siempre se ha hecho de esa manera? –

+0

Como las conversiones deben existir de todos modos, es más fácil convertir a un solo tipo y aplicar los operadores que implementar los operadores por separado para cada tipo además de las conversiones que ya existen. – murgatroid99

+2

Eso, y la máquina hace implícitamente la aritmética como 'int'. Además, si hay muchas conversiones implícitas, es mucho más probable que el compilador elija una conversión que realmente no pretendía. (Ver PL/I, por ejemplo.) –

5

ushort

La siguiente instrucción de asignación producirá un error de compilación, porque la expresión aritmética sobre el lado derecho del operador de asignación evalúa a int por defecto.

ushort z = x + y; // Error: conversion from int to ushort 

Para solucionar este problema, utilice un reparto:

ushort z = (ushort)(x + y); // OK: explicit conversion 
2

Los operadores de suma disponible en C# sólo se contemplan int, uint, long y datos ulong tipos por lo que en ese caso Está implícitamente lanzando dos instancias ushort al int, luego realizando la adición y th es devolver un int que no se puede convertir implícitamente en ushort.

De la especificación C# 4.0, sección 7.8.4 Adición operador, se puede comprobar que sólo los los siguientes operadores de adición de enteros están disponibles:

int operator +(int x, int y); 
uint operator +(uint x, uint y); 
long operator +(long x, long y); 
ulong operator +(ulong x, ulong y); 

La misma sección también establece:

Los operandos se convierten en los tipos de parámetros de la seleccionada operador, y el tipo de resultado es el tipo de devolución del operador.

que explica por qué esta expresión da como resultado un int.

1

Es porque la suma o resta de ushorts no necesariamente resulta en un ushort. Por ejemplo, el resultado podría ser < 0, que no es un ushort. Por lo tanto, debe indicarle al compilador que no se queje por tipo. Creo que esto debería funcionar: return (ushort) (value1 + value2);

Cuestiones relacionadas