如何申报嵌套的枚举? [英] How do I declare a nested enum?
问题描述
我想声明一个嵌套的枚举,如:
I want to declare a nested enum like:
\\pseudocode
public enum Animal
{
dog = 0,
cat = 1
}
private enum dog
{
bulldog = 0,
greyhound = 1,
husky = 3
}
private enum cat
{
persian = 0,
siamese = 1,
burmese = 2
}
Animal patient1 = Animal.dog.husky;
可以完成吗?
推荐答案
我正在寻找类似的东西,以便为日志系统创建轻量级的分层渠道ID。我不太确定这是值得的努力,但我很乐意把它放在一起,我在这个过程中学到了关于操作员重载和蜥蜴的新东西。
I was looking for something similar as a way to create lightweight, hierarchical channel ID's for a logging system. I'm not quite sure this was worth the effort, but I had fun putting it together, and I learned something new about operator overloading and lizards in the process.
我我建立了一个支持这种符号的机制:
I've built a mechanism that supports this notation:
public static class Animal
{
public static readonly ID dog = 1;
public static class dogs
{
public static readonly ID bulldog = dog[0];
public static readonly ID greyhound = dog[1];
public static readonly ID husky = dog[3];
}
public static readonly ID cat = 2;
public static class cats
{
public static readonly ID persian = cat[0];
public static readonly ID siamese = cat[1];
public static readonly ID burmese = cat[2];
}
public static readonly ID reptile = 3;
public static class reptiles
{
public static readonly ID snake = reptile[0];
public static class snakes
{
public static readonly ID adder = snake[0];
public static readonly ID boa = snake[1];
public static readonly ID cobra = snake[2];
}
public static readonly ID lizard = reptile[1];
public static class lizards
{
public static readonly ID gecko = lizard[0];
public static readonly ID komodo = lizard[1];
public static readonly ID iguana = lizard[2];
public static readonly ID chameleon = lizard[3];
}
}
}
你可以使用哪种所以:
void Animalize()
{
ID rover = Animal.dogs.bulldog;
ID rhoda = Animal.dogs.greyhound;
ID rafter = Animal.dogs.greyhound;
ID felix = Animal.cats.persian;
ID zorro = Animal.cats.burmese;
ID rango = Animal.reptiles.lizards.chameleon;
if (rover.isa(Animal.dog))
Console.WriteLine("rover is a dog");
else
Console.WriteLine("rover is not a dog?!");
if (rover == rhoda)
Console.WriteLine("rover and rhoda are the same");
if (rover.super == rhoda.super)
Console.WriteLine("rover and rhoda are related");
if (rhoda == rafter)
Console.WriteLine("rhoda and rafter are the same");
if (felix.isa(zorro))
Console.WriteLine("er, wut?");
if (rango.isa(Animal.reptile))
Console.WriteLine("rango is a reptile");
Console.WriteLine("rango is an {0}", rango.ToString<Animal>());
}
该代码编译并生成以下输出:
That code compiles and produces the following output:
rover is a dog
rover and rhoda are related
rhoda and rafter are the same
rango is a reptile
rango is an Animal.reptiles.lizards.chameleon
这是使其工作的ID结构:
Here's the ID struct that makes it work:
public struct ID
{
public static ID none;
public ID this[int childID]
{
get { return new ID((mID << 8) | (uint)childID); }
}
public ID super
{
get { return new ID(mID >> 8); }
}
public bool isa(ID super)
{
return (this != none) && ((this.super == super) || this.super.isa(super));
}
public static implicit operator ID(int id)
{
if (id == 0)
{
throw new System.InvalidCastException("top level id cannot be 0");
}
return new ID((uint)id);
}
public static bool operator ==(ID a, ID b)
{
return a.mID == b.mID;
}
public static bool operator !=(ID a, ID b)
{
return a.mID != b.mID;
}
public override bool Equals(object obj)
{
if (obj is ID)
return ((ID)obj).mID == mID;
else
return false;
}
public override int GetHashCode()
{
return (int)mID;
}
private ID(uint id)
{
mID = id;
}
private readonly uint mID;
}
这有利于:
- 一个32位的uint作为底层类型
- 将多个小数填充到一个带有位移的整数中(你获得最多四个级别的嵌套ID每个级别有256个条目 - 您可以将级别转换为ulong或更高级别)
- ID 0作为所有ID的特殊根(可能会被称为ID.none) ID.root和任何id.isa(ID.root)应为true)
- 隐式类型转换将int转换为ID
- a indexer 链接ID一起
- 重载相等运算符以支持比较
- a 32-bit uint as the underlying type
- multiple small numbers stuffed into an integer with bit shifts (you get maximum four levels of nested ID's with 256 entries at each level -- you could convert to ulong for more levels or more bits per level)
- ID 0 as the special root of all ID's (possibly ID.none should be called ID.root, and any id.isa(ID.root) should be true)
- implicit type conversion to convert an int into an ID
- an indexer to chain ID's together
- overloaded equality operators to support comparisons
到目前为止铰链效率很高,但是我不得不为ToString采取反思和递归,所以我把它关闭了一个扩展方法,如下所示:
Up to now everything's pretty efficient, but I had to resort to reflection and recursion for ToString, so I cordoned it off in an extension method, as follows:
using System;
using System.Reflection;
public static class IDExtensions
{
public static string ToString<T>(this ID id)
{
return ToString(id, typeof(T));
}
public static string ToString(this ID id, Type type)
{
foreach (var field in type.GetFields(BindingFlags.GetField | BindingFlags.Public | BindingFlags.Static))
{
if ((field.FieldType == typeof(ID)) && id.Equals(field.GetValue(null)))
{
return string.Format("{0}.{1}", type.ToString().Replace('+', '.'), field.Name);
}
}
foreach (var nestedType in type.GetNestedTypes())
{
string asNestedType = ToString(id, nestedType);
if (asNestedType != null)
{
return asNestedType;
}
}
return null;
}
}
请注意,为了这个工作,动物可能不再是静态类,因为不能使用静态类作为类型参数,所以我用私有构造函数将其密封:
Note that for this to work Animal could no longer be a static class, because static classes can't be used as type parameters, so I made it sealed with a private constructor instead:
public /*static*/ sealed class Animal
{
// Or else: error CS0718: 'Animal': static types cannot be used as type arguments
private Animal()
{
}
....
唷!谢谢阅读。 : - )
Phew! Thanks for reading. :-)
这篇关于如何申报嵌套的枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!