您可以在运行时添加到枚举类型

CJ7*_*CJ7 31 c# enums runtime

如果我有枚举类型:

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)

  • 事实并非如此,文字4也可以是一个变量.这是你能得到的最好的. (4认同)

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)

了解此解决方案的不同特点.

  1. 它是一个包含整数值的不可变结构.该值通过readonly关键字强制不可变.

  2. 创建其中一个结构的唯一方法是调用将值作为参数的构造函数.

  3. implicit operator int是否存在这样的结构,可以在结构中使用switch- 即使结构可转换为int.

  4. implicit operator Sport是这样你可以为结构分配整数值,即Sport rugby = 5.

  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具有名称的值类.根据您的应用程序,您可以扩展此类以提供其他属性和方法.将此作为类可以为您提供更多的灵活性,因为您可以将其子类化.

Sportsclass提供了在编译时已知的静态运动集合.这类似于某些.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,它将无限地递归.


Dar*_*rov 5

不,您无法在运行时修改类型.您可以发出新类型,但无法修改现有类型.