在C#中实现枚举对象类型
本文关键字:对象 类型 枚举 实现 | 更新日期: 2023-09-27 18:20:15
我是C#的新手,但我用Java做了很多编程。在Java中,可以通过声明一个具有多个字段和一个私有构造函数的enum
来创建枚举对象类型(一个只有固定数量的可能值的类)。例如,本Java教程展示了如何创建枚举的"Planet"类型,这是一个对象(它有多个数据字段),但具有固定数量的值(只有8个行星,因此该对象只有8个实例)。
然而,在C#中似乎没有任何方法可以做到这一点,因为C#中的enum
只允许是基元类型,特别是数字基元类型。有没有什么简单的方法可以强制C#对象类型具有固定数量的可能实例值?或者我应该采用某种Singleton Pattern/Factory Pattern架构,比如给类一个私有构造函数,并定义固定数量的静态方法来返回一个有效实例?
System.Drawing.Color
就是这种事情的一个例子。
Color
类型具有Color
类型的静态属性集合,这些静态属性提供对命名颜色的访问。例如,System.Drawing.Color.CornflowerBlue
。
Color
类型允许您在不使用命名的颜色静态成员的情况下创建Color
。如果你想禁止这种情况,你可以让你的类只有私有构造函数。那么,访问您类型的实例的唯一方法是选择您类型的一个可用静态属性。
您可以创建一个静态类,该类具有表示您的值的静态属性。这可能是最接近的。
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
类型)都应该是不可变的。否则,您可能会遇到一些恶劣的多线程竞争条件。
枚举从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 );
}
}
}
这有点像黑客,但保留了Enum的语义(例如,在switch
语句中使用它的能力。