我想声明几个常量对象,每个对象都有两个子对象,我想将它们存储在一个enum
用于组织目的。
有可能在 C# 中做这样的事情吗?
enum Car
{
carA = { 'ford', 'red' }
carB = { 'bmw', 'black' }
carC = { 'toyota', 'white' }
}
不,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" });
不,这是不可能的。您可以定义一个静态类
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>
而不是 astring[]
以保留枚举的不变性。
这不满足每个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);
}
不。
首先,C# 中的枚举实际上是整数值,而不是字符串。
其次,枚举中的每个值只能有一个值。
您可以为每个枚举值指定整数值,这将允许枚举中的多个元素具有相同的整数值:
public enum Car
{
Ford = 1,
Red = 1,
Bmw = 2,
Black = 2
// etc.
}
但听起来你真正要找的是字典。
枚举的值始终由整数表示。您不能使用其他类型(如字符串数组)。
您可以执行以下操作以获得类似的结果:
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)};
您可以使用静态类来容纳显示额外数据的扩展方法。例如:
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" };
}
}
}
话虽如此,为此返回一个字符串数组对我来说没有多大意义。相反,我会声明两种扩展方法,一种用于制作,一种用于颜色:
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();
Car
制作作品的一个小技巧enum
,定义:
internal enum Maker
{
Ford, Bmw, Toyota,
}
internal enum Color
{
Red, Black, White
}
然后构建结构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;
属性的使用呢?
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;
}
并调用这个吸气剂,
Cars.CarA.GetMake()
另一种方法是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
}
请注意,这只是示例 - 您应该避免在单个枚举中混合类型的属性(在这种情况下为汽车型号和颜色)。