Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create an enum containg arrays?

Tags:

c#

enums

I want to declare several constant objects that each have two subobjects, and I'd like to store these in an enum for organizational purposes.

Is it possible to do something like this in C#?

enum Car
{
  carA = { 'ford', 'red' }
  carB = { 'bmw', 'black' }
  carC = { 'toyota', 'white' }
}
like image 312
dukenukem Avatar asked Oct 03 '12 16:10

dukenukem


3 Answers

No, the C# language does not allow for that.

You can create a

Dictionary<Car, List<string>> cars;

You would add entries to it like

cars = new Dictionary<Car, List<String>>();
cars.Add(Car.carA, new List<String>() { "ford", "red" });

Note though that if you are mixing the concept of "ford" and "red", you may want to consider creating an object to represent that thing, e.g.

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

Then, your Dictionary object would look like

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

cars.Add(Car.carA, new CarDetails() { Maker = "ford", Color = "red" });
like image 73
Eric J. Avatar answered Oct 26 '22 23:10

Eric J.


No, this is not possible. You can define a static class

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"});
}

I used ReadOnlyCollection<string> instead of a string[] in order to preserve the immutability property of enums.

This doesn't satisfy the condition that each of Car's properties are instances of Car. You could go further to get what you want using a custom enumeration class, with a private constructor and static instances. Jimmy Bogard has an example implementation and base class available at http://lostechies.com/jimmybogard/2008/08/12/enumeration-classes/ . He provides an extensible base class, which you should look into if you will do this a lot. However, just so you get the idea, a simple implementation that uses this approach with your data would look like:

 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); }
}

Now, you can access it in the same way that you use an enum. For example,

 void Main(){
     var blackBeamer = Car.carC;
     Console.WriteLine("carC is a " + blackBeamer.Color +" " + blackBeamer.Make);
 }
like image 26
smartcaveman Avatar answered Oct 26 '22 22:10

smartcaveman


No.

First of all, enums in C# are really integer values, not strings.

Second of all, each value in an enum can only have a single value.

You could specify the integer values for each enum value though, which would allow multiple elements in the enum to have the same integer value:

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

But it sounds like what you're really looking for is a Dictionary.

like image 30
Justin Niessner Avatar answered Oct 26 '22 22:10

Justin Niessner