如何在 C# 中为枚举重载运算符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1355817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:33:42  来源:igfitidea点击:

How do I overload an operator for an enumeration in C#?

c#enumsoperatorsoperator-overloading

提问by ChrisHDog

I have an enumerated type that I would like to define the >, <, >=, and <=operators for. I know that these operators are implictly created on the basis of the enumerated type (as per the documentation) but I would like to explictly define these operators (for clarity, for control, to know how to do it, etc...)

我有一个枚举类型,我想定义的><>=,和<=运营商。我知道这些运算符是在枚举类型的基础上隐式创建的(根据文档),但我想明确定义这些运算符(为了清楚起见,为了控制,知道如何去做,等等......)

I was hoping I could do something like:

我希望我能做这样的事情:

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

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

}

But this doesn't seem to work ("unexpected token") ... is this possible? It seems like it should be since there are implictly defined operators. Any suggestions?

但这似乎不起作用(“意外令牌”)......这可能吗?似乎应该如此,因为存在隐式定义的运算符。有什么建议?

采纳答案by Mehrdad Afshari

You can't do that. You can only provide overloaded operators for classes and structs you define -- and at least one of the parameters should be of type of the class or struct itself. That is, you candeclare an overloaded addition operator that adds a MyClassto MyEnumbut you can never do that with two MyEnumvalues.

你不能那样做。您只能为您定义的类和结构提供重载运算符——并且至少其中一个参数应该是类或结构本身的类型。也就是说,您可以声明一个将 a 添加MyClass到的重载加法运算符,MyEnum但您永远不能使用两个MyEnum值来执行此操作。

回答by Brian Rasmussen

As Mehrdad says, you can't do that on the enum itself. You could however make a couple of extension methods that work on your enum. That will make it look like methods on the enum.

正如 Mehrdad 所说,你不能在枚举本身上做到这一点。但是,您可以制作一些适用于您的枚举的扩展方法。这将使它看起来像枚举上的方法。

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

回答by Boris Modylevsky

As other mentioned before, one cannot override operators on Enums, but you can do it on struct. See an example below. Let me know if it helped:

正如前面提到的,不能覆盖枚举上的运算符,但您可以在结构上覆盖。请参阅下面的示例。如果有帮助,请告诉我:

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

回答by Wojteq

According to ECMA-335 Common Language Infrastructure:

根据 ECMA-335 公共语言基础设施:

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)

CTS 支持枚举(也称为枚举类型),这是现有类型的替代名称。出于匹配签名的目的,枚举不应与基础类型相同。但是,枚举的实例应可分配给基础类型,反之亦然。也就是说,从枚举转换为底层类型不需要强制转换(参见 §8.3.3)或强制转换(参见 §8.3.2),也不需要从底层类型到枚举。枚举比真正的类型受到更多的限制,如下所示:它应该只有一个实例字段,并且该字段的类型定义了枚举的基础类型。

  • 它不应有任何自己的方法。
  • 它应从 System.Enum 派生(请参阅 Partition IV Library – Kernel Package)。
  • 它不应实现自己的任何接口。
  • 它不应有任何自己的财产或事件。
  • 它不应有任何静态字段,除非它们是文字。(见第 8.6.1.2 节)

Let's assume that we've got following IL code:

假设我们有以下 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 compiler (ilasm.exe) will generate following error:

MSIL 编译器 (ilasm.exe) 将产生以下错误:

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

So we can't overload enum operator even editing IL code ;)

因此,即使编辑 IL 代码,我们也不能重载枚举运算符;)

回答by VoteCoffee

You can't override the compareto method, but you can add an extension method:

您不能覆盖 compareto 方法,但可以添加扩展方法:

<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

And then execute it as follows:

然后执行如下:

IntegerResult = myEnum.Compare(otherEnum)

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

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