C# 如何声明嵌套枚举?
我想声明一个嵌套枚举,如:C# 如何声明嵌套枚举?,c#,enums,C#,Enums,我想声明一个嵌套枚举,如: \\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; 能做到
\\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;
能做到吗?简单地说,不,不能
我建议您在
Animal
enum中定义所有值。你有什么理由想要这种特殊的结构吗?我不认为它是这样工作的
枚举应该是一组简单的并行值
您可能希望用继承来表达这种关系。但是您可以使用此方法来获得您想要的
public static class Animal {
public enum Dog {
BullDog,
GreyHound,
Huskey
}
public enum Cat {
Tabby,
Bombbay
}
}
请参见以下问题:这些问题涉及构建基本字符串枚举,但我使用
ICustomEnum
接口实现我的答案,该接口可能在这种情况下对您有所帮助。也许这就足够了
class A
{
public const int Foo = 0;
public const int Bar = 1;
}
class B : A
{
public const int Baz = 2;
}
我可能会使用枚举位字段和扩展方法的组合来实现这一点。例如:
public enum Animal
{
None = 0x00000000,
AnimalTypeMask = 0xFFFF0000,
Dog = 0x00010000,
Cat = 0x00020000,
Alsation = Dog | 0x00000001,
Greyhound = Dog | 0x00000002,
Siamese = Cat | 0x00000001
}
public static class AnimalExtensions
{
public bool IsAKindOf(this Animal animal, Animal type)
{
return (((int)animal) & AnimalTypeMask) == (int)type);
}
}
更新在.NET4中,您可以使用
Enum.HasFlag
方法,而不是滚动您自己的扩展。我一直在寻找类似的方法,为日志系统创建轻量级的分层通道ID。我不太确定这是否值得付出努力,但我很高兴把它放在一起,在这个过程中我学到了一些关于操作符重载和蜥蜴的新知识
public class Animal
{
public Animal(string name = "")
{
Name = name;
Perform = Performs.Nothing;
}
public enum Performs
{
Nothing,
Sleep,
Eat,
Dring,
Moan,
Flee,
Search,
WhatEver
}
public string Name { get; set; }
public Performs Perform { get; set; }
}
public class Cat : Animal
{
public Cat(Types type, string name)
: base (name)
{
Type = type;
}
public enum Types
{
Siamese,
Bengal,
Bombay,
WhatEver
}
public Types Type { get; private set; }
}
public class Dog : Animal
{
public Dog(Types type, string name)
: base(name)
{
Type = type;
}
public enum Types
{
Greyhound,
Alsation,
WhatEver
}
public Types Type { get; private set; }
}
我构建了一个支持这种符号的机制:
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>());
}
下面是使其工作的ID结构:
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;
}
呸!感谢阅读。:-) 这是一个老问题,但我最近想知道这样的事情是否可能。在C#中,似乎没有什么比Enum的继承更好的了,创建类似这样的东西的唯一方法是像yoyo的答案那样的自定义类。问题是它们不是真正的枚举(例如不能在switch语句中使用),而且嵌套代码的性质使得快速阅读和理解非常困难 我发现获得类似行为的最简单方法是使用一个简单的枚举,并用包含关系(继承)的属性装饰枚举。这使得代码更易于阅读和理解:
class AnimalAttribute : Attribute {}
class DogAttribute : AnimalAttribute {}
class CatAttribute : AnimalAttribute {}
class ReptileAttribute : AnimalAttribute {}
class SnakeAttribute : ReptileAttribute {}
class LizardAttribute : ReptileAttribute {}
enum Animal
{
[Dog] bulldog,
[Dog] greyhound,
[Dog] husky,
[Cat] persian,
[Cat] siamese,
[Cat] burmese,
[Snake] adder,
[Snake] boa,
[Snake] cobra,
[Lizard] gecko,
[Lizard] komodo,
[Lizard] iguana,
[Lizard] chameleon
}
现在,枚举可以像普通枚举一样使用,我们可以使用一些简单的扩展方法来检查它们之间的关系:
static class Animals
{
public static Type AnimalType(this Enum value )
{
var member = value.GetType().GetMember(value.ToString()).FirstOrDefault();
// this assumes a single animal attribute
return member == null ? null :
member.GetCustomAttributes()
.Where(at => at is AnimalAttribute)
.Cast<AnimalAttribute>().FirstOrDefault().GetType();
}
public static bool IsCat(this Enum value) { return value.HasAttribute<CatAttribute>(); }
public static bool IsDog(this Enum value) { return value.HasAttribute<DogAttribute>(); }
public static bool IsAnimal(this Enum value) { return value.HasAttribute<AnimalAttribute>(); }
public static bool IsReptile(this Enum value) { return value.HasAttribute<ReptileAttribute>(); }
public static bool IsSnake(this Enum value) { return value.HasAttribute<SnakeAttribute>(); }
public static bool IsLizard(this Enum value) { return value.HasAttribute<LizardAttribute>(); }
public static bool HasAttribute<T>(this Enum value)
{
var member = value.GetType().GetMember(value.ToString()).FirstOrDefault();
return member != null && Attribute.IsDefined(member, typeof(T));
}
public static string ToString<T>(this Animal value) where T : AnimalAttribute
{
var type = value.AnimalType();
var s = "";
while( type != null && !(type == typeof(Object)) )
{
s = type.Name.Replace("Attribute","") + "."+s;
type = type.BaseType;
}
return s.Trim('.');
}
}
这是我的解决方案/解决方案:
public static class Categories
{
public const string Outlink = "Outlink";
public const string Login = "Login";
}
public enum Action
{
/// <summary>
/// Outlink is a anchor tag pointing to an external host
/// </summary>
[Action(Categories.Outlink, "Click")]
OutlinkClick,
[Action(Categories.Outlink, "ClickBlocked")]
OutlinkClickBlocked,
/// <summary>
/// User account events
/// </summary>
[Action(Categories.Login, "Succeeded")]
LoginSucceeded,
[Action(Categories.Login, "Failed")]
LoginFailed
}
public class ActionAttribute : Attribute
{
public string Category { get; private set; }
public string Action { get; private set; }
public ActionAttribute(string category, string action)
{
Category = category;
Action = action;
}
}
公共静态类类别
{
公共常量字符串Outlink=“Outlink”;
public const string Login=“Login”;
}
公开枚举操作
{
///
///Outlink是指向外部主机的定位标记
///
[操作(Categories.Outlink,“单击”)]
大纲视图单击,
[操作(Categories.Outlink,“ClickBlocked”)]
大纲链接被阻止,
///
///用户帐户事件
///
[操作(Categories.Login,“成功”)]
登录成功,
[操作(Categories.Login,“失败”)]
登录失败
}
公共类ActionAttribute:属性
{
公共字符串类别{get;private set;}
公共字符串操作{get;private set;}
公共操作属性(字符串类别、字符串操作)
{
类别=类别;
行动=行动;
}
}
此解决方案返回int
,而不是type
。但我是这样使用它的:
public static class Animals
{
public static class Vertebrates
{
public static class Mammals
{
public enum Dogs
{
BullDog = 0,
Greyhound = 1
}
public enum Cats
{
persian = 0,
Greyhound = 1
}
}
public static class Birds
{
public enum FirstType
{
FirstType0 = 0,
FirstType1 = 1
}
public enum SecondType
{
SecondType0 = 0,
SecondType1 = 1
}
}
}
}
用法:
int i = (int)Animals.Vertebrates.Mammals.Dogs.BullDog;
int j = (int)Animals.Vertebrates.Birds.FirstType.FirstType0;
如果他需要表达的唯一信息是动物的类型,那么创建带有继承的类层次结构可能不是最好的主意。这不是OO的方式。为什么不使用类继承来执行此操作?对我来说,animal1听起来像是一个对象……如果动物的类型只是一个值,那么首先为什么要麻烦层次结构呢?实际的枚举是Editjob、AddJobcard、EditInstallation、AddInstallation等。在移动应用程序中使用这些枚举来切换共享用户控件的控件的活动/非活动,以及一些地方设置控件的可见性。这是一个公平的建议,虽然我仍然不知道我会怎么做。它提供了正确的语法,但不是必要的继承。就CLR而言,狗和猫是完全不相关的。简单地定义单个动物枚举中的所有值表明它们在某种形式上是同质的(即所有动物)。考虑:如何将狗或猫作为参数传递?无法响应OP的输入请求:
Animal patient1=Animal.Dog.husky
@Noldorin,你将如何传递狗或猫作为参数?
我们可以传递为Animal.Dog.BullDog
你将如何准确地将其传递到方法中?方法params必须是Animal.Dog或Animal.Cat,这违背了它的全部目的。我有这样的方法,但想将主枚举细分为下面的不同组。我做了一些非常类似的事情。我添加了一个带有静态成员函数的支持类,该函数将接受一个枚举值(husky、persian等)并返回另一个枚举值(dog或cat)。大多数代码都保留了原始的枚举,但是在我想为用户组织内容的地方,我可以很容易地得到值是猫还是狗。支持类有一个静态字典,映射为husky=>dog,等等。我认为这个解决方案在设计(反OOD)、可读性和维护方面都很差。这是一个有趣的观点。你能为这个结论提供一些理由吗?我很想听听。我认为正在解决的问题会导致一些笨拙的设计;它们只是类型安全常量。假设存在一些对某些物种无效的品种,则上述枚举不符合建议,即当某些值组合从中无效时,避免创建标志枚举。您应该用[flags]
装饰动物+1因为答案很简单。你永远不能比较动物,因为所有的猫都有相同的价值。另外,return(AnimalGroup)animal==groupnNumber
Wow,5年后!虽然我已经换了两次工作,但我记得你们的解决方案正是我想要的
static class Animals
{
public static Type AnimalType(this Enum value )
{
var member = value.GetType().GetMember(value.ToString()).FirstOrDefault();
// this assumes a single animal attribute
return member == null ? null :
member.GetCustomAttributes()
.Where(at => at is AnimalAttribute)
.Cast<AnimalAttribute>().FirstOrDefault().GetType();
}
public static bool IsCat(this Enum value) { return value.HasAttribute<CatAttribute>(); }
public static bool IsDog(this Enum value) { return value.HasAttribute<DogAttribute>(); }
public static bool IsAnimal(this Enum value) { return value.HasAttribute<AnimalAttribute>(); }
public static bool IsReptile(this Enum value) { return value.HasAttribute<ReptileAttribute>(); }
public static bool IsSnake(this Enum value) { return value.HasAttribute<SnakeAttribute>(); }
public static bool IsLizard(this Enum value) { return value.HasAttribute<LizardAttribute>(); }
public static bool HasAttribute<T>(this Enum value)
{
var member = value.GetType().GetMember(value.ToString()).FirstOrDefault();
return member != null && Attribute.IsDefined(member, typeof(T));
}
public static string ToString<T>(this Animal value) where T : AnimalAttribute
{
var type = value.AnimalType();
var s = "";
while( type != null && !(type == typeof(Object)) )
{
s = type.Name.Replace("Attribute","") + "."+s;
type = type.BaseType;
}
return s.Trim('.');
}
}
void Main()
{
Animal rover = Animal.bulldog;
Animal rhoda = Animal.greyhound;
Animal rafter = Animal.greyhound;
Animal felix = Animal.persian;
Animal zorrow = Animal.burmese;
Animal rango = Animal.chameleon;
if( rover.IsDog() )
Console.WriteLine("rover is a dog");
else
Console.WriteLine("rover is not a dog?!");
if( rover == rhoda )
Console.WriteLine("rover and rhonda are the same type");
if( rover.AnimalType() == rhoda.AnimalType() )
Console.WriteLine("rover and rhonda are related");
if( rhoda == rafter )
Console.WriteLine("rhonda and rafter are the same type");
if( rango.IsReptile() )
Console.WriteLine("rango is a reptile");
Console.WriteLine(rover.ToString<AnimalAttribute>());
}
public static dynamic dogs
{
get {
var eo = new ExpandoObject() as IDictionary<string,object>;
foreach( var value in Enum.GetValues(typeof(Animal)).Cast<Animal>().Where(a => a.IsDog()))
eo[value.ToString()] = value;
return eo;
}
}
public static dynamic cats
{
get {
var eo = new ExpandoObject() as IDictionary<string,object>;
foreach( var value in Enum.GetValues(typeof(Animal)).Cast<Animal>().Where(a => a.IsCat()))
eo[value.ToString()] = value;
return eo;
}
}
Animal rhoda = Animals.dogs.greyhound;
Animal felix = Animals.cats.persian;
public static class Categories
{
public const string Outlink = "Outlink";
public const string Login = "Login";
}
public enum Action
{
/// <summary>
/// Outlink is a anchor tag pointing to an external host
/// </summary>
[Action(Categories.Outlink, "Click")]
OutlinkClick,
[Action(Categories.Outlink, "ClickBlocked")]
OutlinkClickBlocked,
/// <summary>
/// User account events
/// </summary>
[Action(Categories.Login, "Succeeded")]
LoginSucceeded,
[Action(Categories.Login, "Failed")]
LoginFailed
}
public class ActionAttribute : Attribute
{
public string Category { get; private set; }
public string Action { get; private set; }
public ActionAttribute(string category, string action)
{
Category = category;
Action = action;
}
}
public static class Animals
{
public static class Vertebrates
{
public static class Mammals
{
public enum Dogs
{
BullDog = 0,
Greyhound = 1
}
public enum Cats
{
persian = 0,
Greyhound = 1
}
}
public static class Birds
{
public enum FirstType
{
FirstType0 = 0,
FirstType1 = 1
}
public enum SecondType
{
SecondType0 = 0,
SecondType1 = 1
}
}
}
}
int i = (int)Animals.Vertebrates.Mammals.Dogs.BullDog;
int j = (int)Animals.Vertebrates.Birds.FirstType.FirstType0;