我们可以在 C# 中定义枚举的隐式转换吗?
是否可以在 C# 中定义枚举的隐式转换?
可以实现这一点的东西吗?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
如果没有,为什么不呢?
Is it possible to define an implicit conversion of enums in c#?
something that could achieve this?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
If not, why not?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
有一个解决方案。 考虑以下事项:
上面提供了隐式转换:
这比声明普通枚举要多做一些工作(尽管您可以将上面的一些内容重构为通用的通用基类)。 您可以通过让基类实现 IComparable & 来更进一步。 IEquatable,以及添加方法来返回 DescriptionAttributes 的值、声明的名称等。
我编写了一个基类 (RichEnum<>) 来处理大部分繁重的工作,这将上面的枚举声明简化为:
下面列出了基类 (RichEnum)。
There is a solution. Consider the following:
The above offers implicit conversion:
This is a fair bit more work than declaring a normal enum (though you can refactor some of the above into a common generic base class). You can go even further by having the base class implement IComparable & IEquatable, as well as adding methods to return the value of DescriptionAttributes, declared names, etc, etc.
I wrote a base class (RichEnum<>) to handle most fo the grunt work, which eases the above declaration of enums down to:
The base class (RichEnum) is listed below.
您不能进行隐式转换(除了零),并且您不能编写自己的实例方法 - 但是,您可能可以编写自己的扩展方法:
不过,这并没有给您带来很多好处(与仅执行显式转换)。
我看到人们希望这样做的主要时间之一是通过泛型进行
[Flags]
操作 - 即bool IsFlagSet(T value, T flag);
方法。 不幸的是,C# 3.0 不支持泛型运算符,但您可以使用 这样的事情,这使得运算符完全可以与泛型一起使用。You can't do implict conversions (except for zero), and you can't write your own instance methods - however, you can probably write your own extension methods:
This doesn't give you a lot, though (compared to just doing an explicit cast).
One of the main times I've seen people want this is for doing
[Flags]
manipulation via generics - i.e. abool IsFlagSet<T>(T value, T flag);
method. Unfortunately, C# 3.0 doesn't support operators on generics, but you can get around this using things like this, which make operators fully available with generics.我改编了 Mark 优秀的 RichEnum 通用基类。
修复了
感谢 Mark 出色的想法 + 实现,在此向大家致敬:
我在 mono 上运行的使用示例:
生成输出
注意:mono 2.6.7 需要额外的显式转换,而使用 mono 2.8.2 时则不需要。 ..
I adapted Mark's excellent RichEnum generic baseclass.
Fixing
Kudos to Mark for the splendid idea + implementation, here's to you all:
A sample of usage that I ran on mono:
Producing the output
Note: mono 2.6.7 requires an extra explicit cast that is not required when using mono 2.8.2...
您无法在枚举类型上声明隐式转换,因为它们无法定义方法。 C# 隐式 关键字编译成以'op_',在这种情况下它不起作用。
You cannot declare implicit conversions on enum types, because they can't define methods. The C# implicit keyword compiles into a method starting with 'op_', and it wouldn't work in this case.
你可能可以,但不能用于枚举(你不能向它添加方法)。 您可以向自己的类添加隐式转换,以允许将枚举转换为它,
问题是为什么?
一般来说,.Net 避免(你也应该)任何可能丢失数据的隐式转换。
You probably could, but not for the enum (you can't add a method to it). You could add an implicit conversion to you own class to allow an enum to be converted to it,
The question would be why?
In general .Net avoids (and you should too) any implicit conversion where data can be lost.
因此,枚举对我来说基本上没用,OP。
我最终总是做与图片相关的事情:
简单的解决方案
经典示例问题是 VirtualKey 设置用于检测按键。
这里的问题是你不能用枚举索引数组,因为它不能隐式地将枚举转换为ushort(即使我们甚至基于ushort的枚举)
在这个特定的上下文中,枚举被以下数据结构废弃
。 。 。 。
enums are largely useless for me because of this, OP.
I end up doing pic-related all the time:
the simple solution
classic example problem is the VirtualKey set for detecting keypresses.
problem here is you can't index the array with the enum because it can't implicitly convert enum to ushort (even though we even based the enum on ushort)
in this specific context, enums are obsoleted by the following datastructure
. . . .
我发现从这里获取更简单的解决方案 https://codereview.stackexchange.com/questions/ 7566/enum-vs-int-wrapper-struct 我从该链接粘贴了下面的代码,以防它将来不起作用。
I found even easier solution taken from here https://codereview.stackexchange.com/questions/7566/enum-vs-int-wrapper-struct I pasted the code below from that link just in case it does not work in the future.
我创建这个实用程序是为了帮助我将 Enum 转换为 PrimitiveEnum 和 PrimitiveEnum 转换为
byte、sbyte、short、ushort、int、uint 、long 或 ulong
。因此,从技术上讲,这会将任何枚举转换为其任何原始值。
请参阅提交 https ://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
I created this utility to help me convert an Enum to PrimitiveEnum and PrimitiveEnum to
byte, sbyte, short, ushort, int, uint, long, or ulong
.So, this technically converts any enum to any its primitive value.
See commit at https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
如果将枚举的基数定义为 long,则可以执行显式转换。 我不知道是否可以使用隐式转换,因为枚举不能在其上定义方法。
另外,请注意,未初始化的枚举将默认为 0 值或第一项 - 因此在上述情况下,最好也定义
zero = 0
。If you define the base of the enum as a long then you can perform explicit conversion. I don't know if you can use implicit conversions as enums cannot have methods defined on them.
Also, be aware with this that an uninitalised enumeration will default to the 0 value, or the first item - so in the situation above it would probably be best to define
zero = 0
as well.在 MS .net(非 Mono)上运行代码时,我已经解决了 sehe 的答案 的问题。 对我来说,这个问题特别发生在 .net 4.5.1 上,但其他版本似乎也受到了影响。
通过反射(通过
FieldInfo.GetValue(null)
)访问public static TDervied MyEnumValue
的问题不会初始化所述字段。
解决方法
而不是分配在
RichEnum
的静态初始化器上为TDerived
实例命名,这是在第一次访问TDerived.Name
时延迟完成的。 :在我的例子中,它基于
EquatableBase
:注意
上述代码并未包含 Mark 的原始答案!
感谢
Mark 提供他的
RichEnum
实施并感谢 sehe 提供一些改进!I've worked around an issue with sehe's answer when running the code on MS .net (non-Mono). For me specifically the issue occurred on .net 4.5.1 but other versions seem affected, too.
The issue
accessing a
public static TDervied MyEnumValue
by reflection (viaFieldInfo.GetValue(null)
does not initialize said field.The workaround
Instead of assigning names to
TDerived
instances upon the static initializer ofRichEnum<TValue, TDerived>
this is done lazily on first access ofTDerived.Name
. The code:which - in my case - is based upon
EquatableBase<T>
:Note
The above code does not incorporate all features of Mark's original answer!
Thanks
Thanks to Mark for providing his
RichEnum
implementation and thanks to sehe for providing some improvements!这是基于 adminSoftDK 的答案的不同风格。
这允许您将这个
struct
与switch
语句一起使用,我认为这非常棒。Here's a different flavour based on adminSoftDK's answer.
This allows you to use this
struct
withswitch
statements which I think is pretty awesome.@BatteryBackupUnit
嘿,这听起来是一个很酷的解决方案,但是你能在这里解释一下这部分吗?
由于我在 .NET 4.7.2 中遇到了“InvalidCastException”,令人遗憾的是:/
不知道为什么,我创建了 RichEnum 的派生类型,并按照您在示例中所做的一切进行了初始化,但我得到了这个 annyoingg 异常。
我 很高兴对此有所帮助,因为我非常喜欢这种方法。
@BatteryBackupUnit
Hey this sounds like a cool solution but could you explain this part here?
Since im getting with .NET 4.7.2 an "InvalidCastException" out of this sadly :/
I dont know why, i have created a derived type of the RichEnum and initialized as everything u did in the example but i getthis annyoingg exception..
Would be glad of some help to this since i like this approach alot tbh.
我没有足够的代表来添加评论,但我受到了此处“struct”评论的启发:
https://stackoverflow.com/a/39141171/12135042
这是我的做法:
我觉得这是最好的这里有两个世界,因为您获得了超级枚举,以及可作为超级枚举子集静态访问的易于访问的结构。
I don't have enough rep to add a comment, but I was inspired by the 'struct' comment here:
https://stackoverflow.com/a/39141171/12135042
Here is how I did it:
I feel this gets the best of both worlds here, since you get your super enum, and easily accessible structs that are statically accessibly acting as subsets of the superenum.
为枚举类型引入隐式转换会破坏类型安全,因此我不建议这样做。 你为什么想这么做? 我见过的唯一用例是当您想要将枚举值放入具有预定义布局的结构中时。 但即便如此,您也可以在结构中使用枚举类型,并告诉 Marshaller 他应该对此做什么。
Introducing implicit conversions for enum types would break type safety, so I'd not recommend to do that. Why would you want to do that? The only use case for this I've seen is when you want to put the enum values into a structure with a pre-defined layout. But even then, you can use the enum type in the structure and just tell the Marshaller what he should do with this.