tipo - ¿Por qué el compilador de C#no llama al operador de conversión implícito?
que es c sharp (2)
Esa es una pregunta interesante ... funciona con Decimal
, por ejemplo, pero no con TimeSpan
, que son tipos de .NET apropiados (a diferencia de float
etc. que son primativos) y ambos tienen un operador +. ¡Curioso!
Por supuesto, puedes torcer el brazo con:
Money m3 = (Money)m1 + (Money)m2;
Y si usas Nullable<T>
funcionará gratis, por supuesto, además de que obtienes compatibilidad con el compilador + tiempo de ejecución (boxeo). ¿Hay alguna razón para no usar Nullable<T>
aquí?
Veré las especificaciones; MyNullable<T>
tanto, podría pensar en promocionar al operador a MyNullable<T>
; con Nullable<T>
regular, el compilador C # proporciona operadores "levantados" para aquellos compatibles con el tipo, pero no puede hacerlo usted mismo. Lo mejor que puede hacer es ofrecer todos los obvios y esperar que el tipo lo soporte ;-p Para acceder a los operadores con genéricos, consulte aquí , disponible para descarga gratuita aquí .
Tenga en cuenta que probablemente desee aplicar los controles "levantados" apropiados, es decir,
x + y => (x.HasValue && y.HasValue)
? new MyNullable<T>(x.Value + y.Value)
: new MyNullable<T>();
Actualizar
El manejo diferente parece estar relacionado con 14.7.4 (ECMA 334 v4) "Operador de adición", donde está predefinido para un rango de tipos que incluye el decimal (por lo que fue una mala prueba para mí), ya que por 14.2.4 ( mismo) "Resolución de sobrecarga del operador binario", los operadores predefinidos reciben una mención especial. Sin embargo, no pretendo entenderlo completamente.
Supongamos que tenemos el siguiente tipo:
struct MyNullable<T> where T : struct
{
T Value;
public bool HasValue;
public MyNullable(T value)
{
this.Value = value;
this.HasValue = true;
}
public static implicit operator T(MyNullable<T> value)
{
return value.HasValue ? value.Value : default(T);
}
}
E intente compilar el siguiente fragmento de código:
MyNullable<int> i1 = new MyNullable<int>(1);
MyNullable<int> i2 = new MyNullable<int>(2);
int i = i1 + i2;
Este recortado compilado bien y sin errores. i1 e i2 lanzan al entero y la suma evaluada.
Pero si tenemos el siguiente tipo:
struct Money
{
double Amount;
CurrencyCodes Currency; /*enum CurrencyCode { ... } */
public Money(double amount, CurrencyCodes currency)
{
Amount = amount;
Currency = currency;
}
public static Money operator + (Money x, Money y)
{
if (x.Currency != y.Currency)
// Suppose we implemented method ConvertTo
y = y.ConvertTo(x.Currency);
return new Money(x.Amount + y.Amount, x.Currency);
}
}
Intenta compilar otro fragmento de código:
MyNullable<Money> m1 =
new MyNullable<Money>(new Money(10, CurrenciesCode.USD));
MyNullable<Money> m2 =
new MyNullable<Money>(new Money(20, CurrenciesCode.USD));
Money m3 = m1 + m2;
Y ahora la pregunta, ¿por qué el compilador genera " error CS0019: Operador ''+'' no se puede aplicar a los operandos del tipo ''MyNullable <Money>'' y ''MyNullable <Money>'' "?
Marc está en la línea correcta - es la sección 7.2.4 en la especificación C # 3.0 - Resolución de sobrecarga del operador binario.
Básicamente los pasos son:
- Necesitamos resolver la implementación para "X + Y" donde X e Y son ambos
MyNullable<Money>
. - Mirando la sección 7.2.5 (candidatos de operadores definidos por el usuario) terminamos con un conjunto vacío, ya que
MyNullable<T>
no sobrecarga +. - De vuelta en 7.2.4, el conjunto de operadores candidatos es el conjunto integrado de operadores binarios para +, es decir, int + int, decimal + decimal, etc.
- Las reglas de resolución de sobrecarga en 7.4.3 se aplican luego . Cuando hacemos
MyNullable<int> + MyNullable<int>
esto funciona debido a las conversiones implícitas de cada argumento aint
, pero cuando hacemosMyNullable<Money> + MyNullable<Money>
no funciona porqueMoney + Money
no está en el conjunto de operadores candidatos.