2009-08-31 10 views
29

Mam typ wyliczeniowy, który chciałbym zdefiniować operatorów>, <,> = i < = dla. Wiem, że operatory te są tworzone w sposób domyślny na podstawie wyliczonego typu (zgodnie z documentation), ale chciałbym wyraźnie zdefiniować te operatory (dla jasności, kontroli, wiedzieć, jak to zrobić, itp ...)Jak przeciążać operatora dla wyliczenia w C#?

miałem nadzieję, mógłby zrobić coś takiego:

public enum SizeType 
{ 
    Small = 0, 
    Medium = 1, 
    Large = 2, 
    ExtraLarge = 3 
} 

public SizeType operator >(SizeType x, SizeType y) 
{ 

} 

Ale to nie wydają się działać („nieoczekiwany Toke”) ... czy to możliwe? Wygląda na to, że powinno być, ponieważ istnieją implicite zdefiniowane operatory. Jakieś sugestie?

Odpowiedz

31

Nie możesz tego zrobić. Możesz podać tylko przeciążone operatory dla zdefiniowanych klas i struktur - a przynajmniej jeden z parametrów powinien być typu klasy lub samej struktury. Oznacza to, że można można zadeklarować przeciążony operator dodawania, który dodaje MyClass do MyEnum, ale nigdy nie można tego zrobić z dwiema wartościami MyEnum.

+0

to rozczarowujące, jak oni to robią, że implictly wtedy? Wyglądało na to, że nie będzie sposobu, ale pomyślałem, że jeśli można to zrobić w sposób dorozumiany, to powinien istnieć sposób, aby to zrobić w sposób wybiórczy. Nie sądzę. Dzięki za informację. – ChrisHDog

+0

Nie robią tego. Nie ma też * niejawnego * sposobu. Po prostu nie można przeciążać operatorów do wyliczenia. –

+0

Zgodnie z: http://msdn.microsoft.com/en-us/library/aa664726 (VS.71).aspx ... "Każdy typ wyliczenia domyślnie zawiera następujące predefiniowane operatory porównania:" ... ja po prostu mając nadzieję, że istnieje sposób, aby w sposób wyraźny podać operator porównania w podobny sposób. Więc nie jest to operator przeciążający, ale coś prostego. – ChrisHDog

11

Jak mówi Mehrdad, nie można tego zrobić w samym enum. Można jednak utworzyć kilka metod rozszerzania, które działają w twoim wyliczeniu. To sprawi, że będzie wyglądać jak metoda na enumie.

static bool IsLessThan(this SizeType first, SizeType second) { 
} 
20

Jako inny wspomniano wcześniej, nie można zastąpić operatorów na wyliczenia, ale można to zrobić na struct. Zobacz przykład poniżej. Daj mi znać, czy to pomogło:

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 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"); 
     } 
    } 
} 
+0

Wyliczenie może być użyte w instrukcji switch, podczas gdy struct nie może. –

+0

@MikedeKlerk to częściowo zmienione w C# 7.0 https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/ – MaLiN2223

16

Według ECMA-335 Common Language Infrastructure:

The CTS supports an enum (also known as an enumeration type), an alternate name for an existing type. For the purposes of matching signatures, an enum shall not be the same as the underlying type. Instances of an enum, however, shall be assignable-to the underlying type, and vice versa. That is, no cast (see §8.3.3) or coercion (see §8.3.2) is required to convert from the enum to the underlying type, nor are they required from the underlying type to the enum. An enum is considerably more restricted than a true type, as follows: It shall have exactly one instance field, and the type of that field defines the underlying type of the enumeration.

  • It shall not have any methods of its own.
  • It shall derive from System.Enum (see Partition IV Library – Kernel Package).
  • It shall not implement any interfaces of its own.
  • It shall not have any properties or events of its own.
  • It shall not have any static fields unless they are literal. (see §8.6.1.2)

Załóżmy, że mamy następujący kod 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 

MSIL kompilatora (ilasm.exe) wygeneruje następujący błąd:

error -- Method in enum 
***** FAILURE *****

Więc nie możemy przeciążać operatora enum nawet edytowania kodu IL;)

+0

Cenne informacje! –

3

Nie można zastąpić metodę compareTo, ale można dodać metodę rozszerzenia:

<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 

a następnie wykonać ją następująco :

IntegerResult = myEnum.Compare(otherEnum) 

Od http://msdn.microsoft.com/en-us/library/bb384936.aspx