tutorial - ¿Cómo sobrecargo a un operador por una enumeración en C#?
what is a namespace in c# (5)
Tengo un tipo enumerado para el que me gustaría definir los operadores >
, <
, >=
y <=
. Sé que estos operadores se crean implícitamente sobre la base del tipo enumerado (según la documentation ), pero me gustaría definir explícitamente estos operadores (por claridad, por control, para saber cómo hacerlo, etc.)
Esperaba poder hacer algo como:
public enum SizeType
{
Small = 0,
Medium = 1,
Large = 2,
ExtraLarge = 3
}
public SizeType operator >(SizeType x, SizeType y)
{
}
Pero esto no parece funcionar ("token inesperado") ... ¿es esto posible? Parece que debería ser así porque hay operadores definidos implícitamente. ¿Alguna sugerencia?
Como dice Mehrdad, no puedes hacer eso en la enumeración misma. Sin embargo, puedes hacer un par de métodos de extensión que funcionen en tu enumeración. Eso hará que se vea como métodos en la enumeración.
static bool IsLessThan(this SizeType first, SizeType second) {
}
Como se mencionó anteriormente, uno no puede anular operadores en Enums, pero puede hacerlo en struct. Vea un ejemplo a continuación. Avíseme si ayudó:
public struct SizeType
{
private int InternalValue { get; set; }
public static readonly int Small = 0;
public static readonly int Medium = 1;
public static readonly int Large = 2;
public static readonly int ExtraLarge = 3;
public override bool Equals(object obj)
{
SizeType otherObj = (SizeType)obj;
return otherObj.InternalValue.Equals(this.InternalValue);
}
public static bool operator >(SizeType left, SizeType right)
{
return (left.InternalValue > right.InternalValue);
}
public static bool operator <(SizeType left, SizeType right)
{
return (left.InternalValue < right.InternalValue);
}
public static implicit operator SizeType(int otherType)
{
return new SizeType
{
InternalValue = otherType
};
}
}
public class test11
{
void myTest()
{
SizeType smallSize = SizeType.Small;
SizeType largeType = SizeType.Large;
if (smallSize > largeType)
{
Console.WriteLine("small is greater than large");
}
}
}
De acuerdo con ECMA-335 Common Language Infrastructure:
El CTS admite una enumeración (también conocida como tipo de enumeración), un nombre alternativo para un tipo existente. A los efectos de la coincidencia de firmas, una enumeración no será la misma que el tipo subyacente. Sin embargo, las instancias de una enumeración se pueden asignar al tipo subyacente y viceversa. Es decir, no se requiere conversión (ver §8.3.3) o coerción (ver §8.3.2) para convertir de la enumeración al tipo subyacente, ni se requieren desde el tipo subyacente a la enumeración. Una enumeración es considerablemente más restringida que un tipo verdadero, de la siguiente manera: tendrá exactamente un campo de instancia, y el tipo de ese campo define el tipo subyacente de la enumeración.
- No tendrá ningún método propio.
- Se derivará de System.Enum (ver Partition IV Library - Kernel Package).
- No implementará ninguna interfaz propia.
- No debe tener ninguna propiedad o evento propio.
- No debe tener campos estáticos a menos que sean literales. (ver §8.6.1.2)
Supongamos que tenemos el siguiente código IL:
.class public auto ansi sealed Test.Months extends [mscorlib]System.Enum
{
.field public specialname rtspecialname int32 value__
.field public static literal valuetype Test.Months January = int32(0x00000001)
.field public static literal valuetype Test.Months February = int32(0x00000002)
.field public static literal valuetype Test.Months March = int32(0x00000003)
// ...
.method public hidebysig specialname static valuetype Test.Months
op_Increment(valuetype Test.Months m) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 10
IL_0003: add
IL_0004: ret
}
} // end of class Test.Months
El compilador MSIL (ilasm.exe) generará el siguiente error:
error -- Method in enum ***** FAILURE *****
Así que no podemos sobrecargar al operador enum incluso editando el código IL;)
No puede anular el método compareto, pero puede agregar un método de extensión:
<Runtime.CompilerServices.Extension()>
Public Function Compare(ByVal obj1 As EnumType, ByVal obj2 As EnumType) as integer
Dim CompareResults as integer = 0
''some code here to do your comparison
Return CompareResults
End Sub
Y luego ejecútelo de la siguiente manera:
IntegerResult = myEnum.Compare(otherEnum)
No puedes hacer eso. Solo puede proporcionar operadores sobrecargados para las clases y estructuras que defina, y al menos uno de los parámetros debe ser del tipo de la clase o estructura en sí. Es decir, puede declarar un operador adicional sobrecargado que agrega un MyClass
a MyEnum
pero nunca puede hacer eso con dos valores MyEnum
.