在C#中实现枚举对象类型

时间:2013-06-28 19:06:27

标签: c# java enums

我是C#的新手,但我已经用Java做了很多编程。在Java中,您可以通过声明具有多个字段和私有构造函数的enum来创建枚举对象类型(仅具有固定数量的可能值的类)。例如,this Java tutorial显示了如何创建枚举的“Planet”类型,它是一个对象(它有多个数据字段)但是具有固定数量的值(只有8个行星,所以只有8个实例这个对象永远存在)。

但是,似乎没有办法在C#中执行此操作,因为C#中的enum只允许是基本类型,特别是数字基元类型。有没有简单的方法强制C#对象类型具有固定数量的可能实例值?或者我应该采用某种单例模式/工厂模式体系结构,例如为类提供私有构造函数并定义返回其中一个有效实例的固定数量的静态方法?

3 个答案:

答案 0 :(得分:1)

System.Drawing.Color就是这种事情的一个例子。

Color类型具有Color类型的静态属性集合,可提供对命名颜色的访问。例如,System.Drawing.Color.CornflowerBlue

Color类型允许您在不使用命名颜色静态成员的情况下创建Color。如果要禁止此操作,可以使您的类只有私有构造函数。然后,访问您的类型实例的唯一方法是选择您的类型的可用静态属性之一。

答案 1 :(得分:0)

您可以创建一个静态类,它具有代表您的值的静态属性。这可能差不多了。

public static class Planets
{
    // static cctor
    static Planets()
    {
        Saturn = new SaturnPlanet();
        Earth = new EarthPlanet();
        ...
    }

    public static Planet Saturn { get; private set; }
    public static Planet Earth { get; private set; }
    ...
}

您也可以选择在此处公开枚举器或IEnumerable方法或属性。

为了理智,您的Planets类及其所有属性对象(在本例中为Planet类型)应该是不可变的。否则你可能会遇到一些令人讨厌的多线程竞争条件。

答案 2 :(得分:0)

枚举从System.Enum继承并被密封(您不能从枚举继承)。进一步的枚举是在整数类型(short,int,long等)之上的语法糖。你可以这样做:

public enum Planet
{
    Mercury = 1 ,
    Venus   = 2 ,
    Earth   = 3 ,
    Mars    = 4 ,
    Jupiter = 5 ,
    Saturn  = 6 ,
    Uranus  = 7 ,
    Neptune = 8 ,
}
public interface IPlanetData
{
    double Mass   { get ; }
    double Radius { get ; }
}

public static class PlanetEnumHelpers
{
    private class PlanetData : IPlanetData
    {
        internal PlanetData( double mass , double radius )
        {
            Mass = mass ;
            Radius = radius ;
        }
        public double Mass   { get ; private set ; }
        public double Radius { get ; private set ; }
    }
    public static IPlanetData Data( this Planet planet )
    {
        IPlanetData instance ;

        switch ( planet )
        {
            case Planet.Mercury : instance = Mercury ; break ;
            case Planet.Venus   : instance = Venus   ; break ;
            case Planet.Earth   : instance = Earth   ; break ;
            case Planet.Mars    : instance = Mars    ; break ;
            case Planet.Jupiter : instance = Jupiter ; break ;
            case Planet.Saturn  : instance = Saturn  ; break ;
            case Planet.Uranus  : instance = Uranus  ; break ;
            case Planet.Neptune : instance = Neptune ; break ;
            default : throw new ArgumentOutOfRangeException("planet") ;
        }
        return instance ;
    }
    private static IPlanetData Mercury = new PlanetData( 3.303e+23 , 2.4397e6  ) ;
    private static IPlanetData Venus   = new PlanetData( 4.869e+24 , 6.0518e6  ) ;
    private static IPlanetData Earth   = new PlanetData( 5.976e+24 , 6.37814e6 ) ;
    private static IPlanetData Mars    = new PlanetData( 6.421e+23 , 3.3972e6  ) ;
    private static IPlanetData Jupiter = new PlanetData( 1.9e+27   , 7.1492e7  ) ;
    private static IPlanetData Saturn  = new PlanetData( 5.688e+26 , 6.0268e7  ) ;
    private static IPlanetData Uranus  = new PlanetData( 8.686e+25 , 2.5559e7  ) ;
    private static IPlanetData Neptune = new PlanetData( 1.024e+26 , 2.4746e7  ) ;
}
class Program
{
    static void Main( string[] args )
    {
        foreach ( Planet p in Enum.GetValues( typeof( Planet ) ) )
        {
            Console.WriteLine( "{0}: Mass={1} Radius={2}" , p , p.Data().Mass , p.Data().Radius );
        }
    }
}

这有点像黑客,但保留了枚举的语义(例如,能够在switch语句中使用它。