Подтвердить что ты не робот

Как перегрузить оператор для перечисления в С#?

У меня есть перечисляемый тип, который я бы хотел определить для операторов > , <, >= и < =. Я знаю, что эти операторы принудительно создаются на основе перечисленного типа (согласно документации), но я хотел бы явно определить эти операторы ( для ясности, для контроля, знать, как это сделать и т.д.)

Я надеялся, что смогу сделать что-то вроде:

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

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

}

Но это, похоже, не работает ( "неожиданный toke" )... возможно ли это? Похоже, что это должно быть, так как существуют явно определенные операторы. Любые предложения?

4b9b3361

Ответ 1

Вы не можете этого сделать. Вы можете предоставлять только перегруженные операторы для классов и структур, которые вы определяете, и по крайней мере один из параметров должен иметь тип самого класса или структуры. То есть вы можете объявить перегруженный оператор добавления, который добавляет MyClass в MyEnum, но вы никогда не сможете сделать это с двумя значениями MyEnum.

Ответ 2

Как уже упоминалось ранее, нельзя переопределить операторов в Enums, но вы можете сделать это на struct. См. Пример ниже. Сообщите мне, помогло ли это:

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

Ответ 3

В соответствии с ECMA-335 Common Language Infrastructure:

CTS поддерживает перечисление (также известное как тип перечисления), альтернативное имя для существующего типа. Для целей сопоставления подписи, перечисление не должно быть таким же, как базовый тип. Однако экземпляры перечисления должны быть отнесены к основополагающим тип и наоборот. То есть, никакого броска (см. §8.3.3) или принуждения (см. §8.3.2) требуется преобразовать из перечисления в базовый тип, и они не требуются от базового типа к перечислению. Перечисление значительно более ограниченный, чем истинный тип, следующим образом: имеют ровно одно поле экземпляра, и тип этого поля определяет базовый тип перечисления.

  • Он не должен иметь никаких собственных методов.
  • Он должен быть получен из System.Enum(см. раздел IV Library - Kernel Package).
  • Он не должен реализовывать какие-либо интерфейсы.
  • Он не должен иметь никаких свойств или событий.
  • Он не должен иметь никаких статических полей, если они не являются буквальными. (см. §8.6.1.2)

Предположим, что у нас есть код 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-компилятор (ilasm.exe) генерирует следующую ошибку:

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

Таким образом, мы не можем перегружать оператор перечисления даже при редактировании кода IL;)

Ответ 4

Как говорит Мехрдад, вы не можете сделать это на самом перечислении. Однако вы могли бы сделать несколько методов расширения, которые работают над вашим перечислением. Это сделает его похожим на методы перечисления.

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

Ответ 5

Вы не можете переопределить метод сравнения, но вы можете добавить метод расширения:

<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

И затем выполните его следующим образом:

IntegerResult = myEnum.Compare(otherEnum)

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