我想声明几个常量对象,每个对象都有两个子对象,我想将它们存储在enum
中用于组织目的。
是否可以在C#中执行此类操作?
enum Car
{
carA = { 'ford', 'red' }
carB = { 'bmw', 'black' }
carC = { 'toyota', 'white' }
}
答案 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()