【问题标题】:How to Create Two level enum如何创建两级枚举
【发布时间】:2013-09-25 11:43:42
【问题描述】:

对不起,如果问题的标题令人困惑,但我不知道如何提问。 真正想要的是拥有永远不会改变的只读数据。

目前我有两个枚举 MeterTypeSubMeterType

public enum MeterType
{
  Water = 1001,
  Electricity = 1004,
  Gas = 1007
}

public enum SubMeterType
{
  DrinkingWater = 1002,
  UsageWater = 1003,
  SubsidiseGas = 1008,
  NonSusbsidisedGas = 1009
} 

现在我想如下使用这些

获取 MeterType

string meterType = MeterType.Water.ToString("d");

为了获得 SubMeterType,是否有可能拥有类似的东西

string subMeterType = MeterType.Water.DrinkingWater("d");

应该采用另一种方法使用具有只读属性的类吗? 或修改这些枚举以满足我的要求。

【问题讨论】:

  • 换一种方法,可能是字典,否则你最终会得到 SubsidiseGas Water。
  • 也许你想使用java的方法,使用具有常量属性的类而不是枚举
  • @Sayse 你能指导我如何在这种情况下使用字典。
  • 我现在真的没有时间给出一个完整的例子,但是你可以有一个 什么的,老实说,还没有完全想到如何填充这个这就是为什么有一个“可能”前缀
  • @Sayse 我会按照您的建议尝试创建字典。

标签: c# .net oop enums


【解决方案1】:

你不能嵌套enums,但你已经知道了。您可以做的是让constreadonly 属性/字段映射到您想要的各种类型。然后在每种类型中,为子类型定义字段/属性。

public static class MeterTypes
{
    public static readonly Electricity electricity;
    public static readonly Gas gas;
    public static readonly Water water;

    static MeterTypes()
    {
        // initialize the meter types to their default
        MeterTypes.Water = Water.GenericWater;
        MeterTypes.Gas = Gas.GenericGas;
        MeterTypes.Electricity = Electricity.GenericElectricity;
    }

    private MeterTypes()
    {
        // private initialization prevents others from creating the class            
    }

    public class Electricity
    {
        public enum Type
        {
            Generic = 1007,
            SubsidisedElectricity = 1008,
            NonSubsidisedElectricity = 1009
        }

        public static readonly Electricity GenericElectricity;
        public static readonly Electricity SubsidisedElectricity;
        public static readonly Electricity NonSubsidisedElectricity;
        private Type ElectricityType;

        static Electricity()
        {
            SubsidisedElectricity = new Electricity(Type.SubsidisedElectricity);
            NonSubsidisedElectricity = new Electricity(Type.NonSubsidisedElectricity);
            GenericElectricity = new Electricity(Type.Generic);
        }

        // private constructor prevents creation from outside the class
        private Electricity(Type ElectricityType)
        {
            this.ElectricityType = ElectricityType;
        }

        public override string ToString()
        {
            return ElectricityType.ToString();
        }

        public string ToString(string format)
        {
            return ElectricityType.ToString(format);
        }
    }

    public class Gas
    {
        public enum Type
        {
            Generic = 1007,
            SubsidisedGas = 1008,
            NonSubsidisedGas = 1009
        }

        public static readonly Gas GenericGas;
        public static readonly Gas SubsidisedGas;
        public static readonly Gas NonSubsidisedGas;
        private Type gasType;

        static Gas()
        {
            SubsidisedGas = new Gas(Type.SubsidisedGas);
            NonSubsidisedGas = new Gas(Type.NonSubsidisedGas);
            GenericGas = new Gas(Type.Generic);
        }

        // private constructor prevents creation from outside the class
        private Gas(Type gasType)
        {
            this.gasType = gasType;
        }

        public override string ToString()
        {
            return gasType.ToString();
        }

        public string ToString(string format)
        {
            return gasType.ToString(format);
        }
    }

    public class Water
    {
        public enum Type
        {
            Generic = 1001,
            DrinkingWater = 1002,
            UsageWater = 1003
        }

        public static readonly Water GenericWater;
        public static readonly Water DrinkingWater;
        public static readonly Water UsageWater;
        private Type waterType;

        static Water()
        {
            DrinkingWater = new Water(Type.DrinkingWater);
            UsageWater = new Water(Type.UsageWater);
            GenericWater = new Water(Type.Generic);
        }

        // private constructor prevents creation from outside the class
        private Water(Type waterType)
        {
            this.waterType = waterType;
        }

        public override string ToString()
        {
            return waterType.ToString();
        }

        public string ToString(string format)
        {
            return waterType.ToString(format);
        }
    }
}

这个可以这样用

var w = MeterTypes.water; // will give generic water
var uw = MeterTypes.Water.UsageWater // will give usage water

您还可以使用 Enum.ToString() 方法。

您必须注意,此实现依赖于 C# 的区分大小写。这使得MeterTypes.electricityMeterTypes.Electricity 分别引用一个字段和一个类。如果在不区分大小写的语言(例如 VB.NET)中使用此代码,它很可能会失败。您可以通过为 MeterTypes 类中的静态字段使用不同的名称(例如 _Electricity 而不是 electricity)来规避此问题。

【讨论】:

    【解决方案2】:

    您可以在嵌套类中使用常量整数,而不是使用枚举:

    public static class MeterType
    {
        public const int Water = 1001;
        public const int Electricity = 1004;
        public const int Gas = 1007;
    
        public static class Waters
        {
            public const int DrinkingWater = 1002;
            public const int UsageWater = 1003;
        }
    
        public static class Gases
        {
            public const int SubsidiseGas = 1008;
            public const int NonSusbsidisedGas = 1009;
        }
    }
    

    【讨论】:

    • 是的,这符合我的要求,您在编辑之前发布的答案是属性和嵌套类名称相同 public const int Water = 1001;public class Water。使用同名有什么问题吗,因为我可以像 MeterType.WaterMeterType.Water.DrinkingWater 一样使用它
    • @Mourya 您不能同时让 MeterType.WaterMeterType.Water.DrinkingWater 返回 enum 或 int 值。我能想到的最接近的方法是让您拥有MeterType.Water.Value 而不是MeterType.Water,但我认为您对此不感兴趣。
    • @S_F 是的,我想要MeterType.Water
    • @Mourya 复制和粘贴是一件坏事,如果您第一次复制错误的代码。因此编辑。此外,此解决方案是更深层次嵌套枚举的好方法。
    • @Herdo ya 我知道复制/粘贴不好,但我只是检查它是否符合我的要求。
    【解决方案3】:

    只需使用嵌套枚举:

    public class MeterType
    {
        public enum Water { }
    }
    

    但是在这种情况下你不能直接使用MeterType.Water,默认情况下这是不可能的。然后尝试使用嵌套对象或 MeterType 的辅助枚举。

    public enum MeterType { }
    public enum MeterTypeWater { }
    

    在这种情况下,您需要为每个枚举使用不同名称的属性。最好的解决方案是不使用嵌套类:

    public class MeterType
    {
        public static WaterType Water { get; }
    }
    
    public class WaterType
    {
        public readonly SubWaterType DrinkingWater = SubWaterType.DrinkingWater;
    }
    

    【讨论】:

    • 不可能显示预期标识符错误
    • @Co.Aden 当然你需要Water枚举中的条目。应该很清楚了吧?
    • 这给出了错误 public enum saa { public enum dd {ne = 1}, ff = 2 }
    • @Co.Aden 不是嵌套枚举,这是不可能的,嵌套类和枚举。
    • @FelixK。感谢您的回答,但如何才能获得像 MeterType.Water 这样的水的价值?
    猜你喜欢
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 2011-02-26
    相关资源
    最近更新 更多