是否可以创建包含数组的枚举?

时间:2012-10-03 16:23:37

标签: c# enums

我想声明几个常量对象,每个对象都有两个子对象,我想将它们存储在enum中用于组织目的。

是否可以在C#中执行此类操作?

enum Car
{
  carA = { 'ford', 'red' }
  carB = { 'bmw', 'black' }
  carC = { 'toyota', 'white' }
}

8 个答案:

答案 0 :(得分:4)

不,C#语言不允许这样做。

您可以创建

Dictionary<Car, List<string>> cars;

您可以像

一样添加条目
cars = new Dictionary<Car, List<String>>();
cars.Add(Car.carA, new List<String>() { "ford", "red" });

请注意,如果您混合使用“福特”和“红色”的概念,您可能需要考虑创建一个对象来表示该事物,例如。

public class CarDetails
{
    public string Maker { get; set; }
    public string Color { get; set; }
}

然后,您的Dictionary对象看起来像

Dictionary<Car, CarDetails> cars;
cars = new Dictionary<Car.carA, CarDetails>();

cars.Add(Car.carA, new CarDetails() { Maker = "ford", Color = "red" });

答案 1 :(得分:3)

不,这是不可能的。您可以定义静态类

public static class Car
{
    public static readonly ReadOnlyCollection<string> carA = Array.AsReadOnly(new[]{"ford","red"});
    public static readonly ReadOnlyCollection<string> carB = Array.AsReadOnly(new[]{"bmw","black"});
    public static readonly ReadOnlyCollection<string> carC = Array.AsReadOnly(new[]{"toyota","white"});
}

我使用ReadOnlyCollection<string>代替string[]来保留枚举的不变性属性。

这不满足Car的每个属性都是Car的实例的条件。您可以使用自定义枚举类,私有构造函数和静态实例,进一步获取所需内容。 Jimmy Bogard在http://lostechies.com/jimmybogard/2008/08/12/enumeration-classes/有一个示例实现和基类。他提供了一个可扩展的基类,如果你这么做的话,你应该研究一下。但是,只有这样您才能理解,使用此方法对您的数据执行的简单实现如下所示:

 public sealed class Car  : IEquatable<Car> { 

 // declare and define each of your constants

    public static readonly Car carA = new Car("ford", "red");

    public static readonly Car carB = new Car("bmw", "black");

    public static readonly Car carC = new Car("toyota", "white");


 //  define an instance-scoped value object to hold your subObjects
     private readonly Tuple<string,string> subObjects;

 // a private constructor ensures that all your instances will be constant 
 // and will be defined from within Car
     private Car(string make, string color){
     // require valid sub objects
     if(string.IsNullOrEmpty(make))throw new ArgumentException("Invalid Make","make");
     if(string.IsNullOrEmpty(color))throw new ArgumentException("Invalid Color","color");

     // create a subObjects tuple to hold your values to simplify value comparison
     this.subObjects = Tuple.Create(make,color);
     }

 //  declare public accessors for your 
     public string Make { get { return this.subObjects.Item1; } }
     public string Color { get { return this.subObjects.Item2; } }

 // override Equality for value equality, and resulting consistency across AppDomains
         public override bool Equals(object obj){ return obj is Car && this.Equals((Car)obj); }
     public bool Equals(Car otherCar){ return otherCar != null && this.subObjects.Equals(otherCar.subObjects); }
     public override int GetHashCode(){ return this.subObjects.GetHashCode(); }
         public static bool operator ==(Car left, Car right){ return left == null ? right == null : left.Equals(right); }
         public static bool operator !=(Car left, Car right){ return !(left == right); }

 // override ToString() to provide view of values 
     public override string ToString(){ return string.Format("Car({0},{1})",Make,Color); }
}

现在,您可以像使用enum一样访问它。例如,

 void Main(){
     var blackBeamer = Car.carC;
     Console.WriteLine("carC is a " + blackBeamer.Color +" " + blackBeamer.Make);
 }

答案 2 :(得分:2)

没有

首先,C#中的枚举实际上是整数值,而不是字符串。

其次,枚举中的每个值只能有一个值。

您可以为每个枚举值指定整数值,这将允许枚举中的多个元素具有相同的整数值:

public enum Car
{
    Ford = 1,
    Red = 1,
    Bmw = 2,
    Black = 2
    // etc.
}

但听起来你真正想要的是一本词典。

答案 3 :(得分:1)

枚举的值始终用整数表示。您不能使用其他类型(如字符串数组)。

您可以执行以下操作以获得类似的结果:

Dictionary<Car, string[]> cars;
cars = new Dictionary<Car, string[]>();
cars.Add(Car.carA, new string[]{"ford", "red"});
cars.Add(Car.carB, new string[]{"bmw", "black"});
cars.Add(Car.carC, new string[]{"toyota", "white"});

但是,如果您需要将枚举映射到此类字符串,则只应执行此操作。你似乎在混合各种各样的“东西”,即汽车的品牌和颜色。你应该想到更像的东西:

enum Make {
    Ford,
    BMW,
    Toyota
}

enum Color {
    Red,
    Black,
    White
}

并将汽车表示为:

struct Car {
    Make make;
    Color color;
    public Car(Make m, Color c) { make = m; color = c; }
}

和列表:

Car[] cars = new Car[]{new Car(Make.Ford, Color.Red), new Car(Make.BMW, Make.Black), new Car(Make.Toyota, Make.White)};

答案 4 :(得分:1)

另一种方法是Flags enum

[Flags]
enum Car
{
  None = 0, 
  ModelFord = 1,
  ModelBmw = 2,
  ModelToyota = 4,
  ColorRed = 8,
  ColorBlack = 16,
  carA = ModelFord | ColorRed,
  carB = ModelBmw | ColorBlack,
  carC = ModelToyota  | ColorBlack
}

请注意,这只是样本 - 您应避免在单个枚举中混合使用属性类型(在这种情况下为Car model和color)。

答案 5 :(得分:1)

使Car作为enum的一个小技巧,定义:

internal enum Maker
{
    Ford, Bmw, Toyota,
}

internal enum Color
{
    Red, Black, White
}

然后构建struct Car

public struct Car
{
    private readonly Maker _maker;
    private readonly Color _color;

    public static Car CarA = new Car(Maker.Ford, Color.Red);
    public static Car CarB = new Car(Maker.Bmw, Color.Black);
    public static Car CarC = new Car(Maker.Toyota, Color.White);


    private Car(Maker maker, Color color)
    {
        _maker = maker;
        _color = color;
    }

    public static bool operator ==(Car car1, Car car2)
    {
        return car1._maker == car2._maker && car1._color == car2._color;
    }

    public static bool operator !=(Car car1, Car car2)
    {
        return !(car1 == car2);
    }
}

所以,你可以使用:

 Car a = Car.CarA;
 bool flag = a == Car.CarB;

答案 6 :(得分:1)

您可以使用静态类来容纳表示额外数据的扩展方法。例如:

enum Car
{
    CarA, CarB, CarC
}

public static class Cars 
{
    public static string[] GetDetails(this Car car) 
    {
        switch (car) 
        {
            case CarA: return new[] { "ford", "red" };
            case CarB: return new[] { "bmw", "black" };
            case CarC: return new[] { "toyota", "white" };
        }
    }
}

话虽这么说,但为此我返回一个字符串数组并没有多大意义。我会声明两个扩展方法,一个用于make,另一个用于颜色:

public static class Cars 
{
    public static string GetMake(this Car car) 
    {
        switch (car) 
        {
            case CarA: return "ford";
            case CarB: return "bmw";
            case CarC: return "toyota";
        }
    }

    public static string GetColor(this Car car) 
    {
        switch (car) 
        {
            case CarA: return "red";
            case CarB: return "black";
            case CarC: return "white";
        }
    }
}

然后你可以像这样使用它:

Car car = Car.CarA;
string make = car.GetMake();
string color = car.GetColor();

答案 7 :(得分:1)

属性的使用情况如何?

enum Cars{
  [Make("A Make"), Color("A Color")]
  CarA,

  [Make("B Make"), Color("B Color")]
  CarB
}

然后定义像这样的属性。

public class MakeAttribute : Attribute
    {
        public readonly Make make;
        public MakeAttribute (Make make)
        {
          this.make = make;
        }
    }

为Car类型添加扩展名以获取make属性

public static string GetMake(this Car car)
        {
            var makeAttr = (MakeAttribute[])car.GetType().GetField(car.ToString()).GetCustomAttributes(typeof(MakeAttribute), false))[0];
            return makeAttr.make;
        }

并调用此getter,

Cars.CarA.GetMake()