如果我有枚举类型:
public enum Sport
{
Tennis = 0;
Football = 1;
Squash = 2;
Volleyball = 3;
}
Run Code Online (Sandbox Code Playgroud)
我可以在运行时以某种方式添加:
PingPong = 4
Run Code Online (Sandbox Code Playgroud)
Dan*_*ose 32
枚举有一个后备存储,如果你没有指定它,则默认为int.可以直接指定定义值之外的值:
Sport pingPong = (Sport)4;
Run Code Online (Sandbox Code Playgroud)
然后你可以检查它:
if (value == (Sport)4) {}
Run Code Online (Sandbox Code Playgroud)
这就是为什么你有静态函数Enum.IsDefined()
来检查实际值是否在预期值内.请注意,该函数不适用于复合标志值.
bool isValueDefined = Enum.IsDefined(typeof(Sport), value);
Run Code Online (Sandbox Code Playgroud)
编辑:在Hans Passant的评论之后:你不必使用文字值4.你可以使用任何返回int的东西.例如:
Dictionary<int, string> AdditionalSports = new Dictionary<int, string>();
AdditionalSports.Add(4, "PingPong");
// Usages: if
if (AdditionalSports.ContainsKey(value))
{
// Maybe do something with AdditionalSports[value], i.e. "PingPong"
}
// In a switch:
switch (value)
{
case default:
// Since it won't be found in the enum-defined values
if (AdditionalSports.ContainsKey(value))
{
// Maybe do something with AdditionalSports[value], i.e. "PingPong"
}
}
Run Code Online (Sandbox Code Playgroud)
Igo*_*aka 11
这里有更多以面向对象的方式来实现您想要实现的目标.这个解决方案的灵感来自早期的Java枚举方法:
struct Sport {
readonly int value;
public Sport(int value) {
this.value = value;
}
public static implicit operator int(Sport sport) {
return sport.value;
}
public static implicit operator Sport(int sport) {
return new Sport(sport);
}
public const int Tennis = 0;
public const int Football = 1;
public const int Squash = 2;
public const int Volleyball = 3;
}
//Usage:
Sport sport = Sport.Volleyball;
switch(sport) {
case Sport.Squash:
Console.WriteLine("I bounce really high");
break;
}
Sport rugby = 5;
if (sport == rugby)
Console.WriteLine("I am really big and eat a lot");
Run Code Online (Sandbox Code Playgroud)
了解此解决方案的不同特点.
它是一个包含整数值的不可变结构.该值通过readonly
关键字强制不可变.
创建其中一个结构的唯一方法是调用将值作为参数的构造函数.
implicit operator int
是否存在这样的结构,可以在结构中使用switch
- 即使结构可转换为int
.
implicit operator Sport
是这样你可以为结构分配整数值,即Sport rugby = 5
.
const
值是编译时已知的体育.它们也可以用作case
标签.
public static class Sports {
public static readonly Sport Football = new Sport("Football");
public static readonly Sport Tennis = new Sport("Tennis");
}
public class Sport {
public Sport(string name) {
Name = name;
}
public string Name { get; private set; }
// override object.Equals
public override bool Equals(object obj) {
var other = obj as Sport;
if(other == null) {
return false;
}
return other == this;
}
// override object.GetHashCode
public override int GetHashCode() {
return Name.GetHashCode();
}
public static bool operator == (Sport sport1, Sport sport2) {
if(Object.ReferenceEquals(sport1, null) && Object.ReferenceEquals(sport2 , null))
return true;
if(Object.ReferenceEquals(sport1, null) || Object.ReferenceEquals(sport2, null))
return false;
return sport1.Name == sport2.Name;
}
public static bool operator !=(Sport sport1, Sport sport2) {
return !(sport1 == sport2);
}
}
Run Code Online (Sandbox Code Playgroud)
这将创建一个Sport
具有名称的值类.根据您的应用程序,您可以扩展此类以提供其他属性和方法.将此作为类可以为您提供更多的灵活性,因为您可以将其子类化.
Sports
class提供了在编译时已知的静态运动集合.这类似于某些.NET框架处理命名颜色(即WPF)的方式.这是用法:
List<Sport> sports = new List<Sport>();
sports.Add(Sports.Football);
sports.Add(Sports.Tennis);
//What if the name contains spaces?
sports.Add(new Sport("Water Polo"));
var otherSport = new Sport("Other sport");
if(sports.Contains(otherSport)) {
//Do something
}
foreach(var sport in sports) {
if(sport == otherSport) {
//Do Something
} else if(sport == Sports.Football) {
//do something else
}
}
Run Code Online (Sandbox Code Playgroud)
一旦你这样做,你会发现实际上很少需要枚举,因为在Sport
课堂上可以处理运动类型的任何条件操作.
编辑意识到我的相等运算符将抛出一个StackOverflowException
我总是忘记写Object.ReferenceEquals(obj,null)
而不是obj==null
,它将无限地递归.