I've been programming in Java for a while and just got thrown onto a project that's written entirely in C#. I'm trying to come up to speed in C#, and noticed enums used in several places in my new project, but at first glance, C#'s enums seem to be more simplistic than the Java 1.5+ implementation. Can anyone enumerate the differences between C# and Java enums, and how to overcome the differences? (I don't want to start a language flame war, I just want to know how to do some things in C# that I used to do in Java). For example, could someone post a C# counterpart to Sun's famous Planet enum example?

public enum Planet {
  MERCURY (3.303e+23, 2.4397e6),
  VENUS   (4.869e+24, 6.0518e6),
  EARTH   (5.976e+24, 6.37814e6),
  MARS    (6.421e+23, 3.3972e6),
  JUPITER (1.9e+27,   7.1492e7),
  SATURN  (5.688e+26, 6.0268e7),
  URANUS  (8.686e+25, 2.5559e7),
  NEPTUNE (1.024e+26, 2.4746e7),
  PLUTO   (1.27e+22,  1.137e6);

  private final double mass;   // in kilograms
  private final double radius; // in meters
  Planet(double mass, double radius) {
      this.mass = mass;
      this.radius = radius;
  }
  public double mass()   { return mass; }
  public double radius() { return radius; }

  // universal gravitational constant  (m3 kg-1 s-2)
  public static final double G = 6.67300E-11;

  public double surfaceGravity() {
      return G * mass / (radius * radius);
  }
  public double surfaceWeight(double otherMass) {
      return otherMass * surfaceGravity();
  }
}

// Example usage (slight modification of Sun's example):
public static void main(String[] args) {
    Planet pEarth = Planet.EARTH;
    double earthRadius = pEarth.radius(); // Just threw it in to show usage

    // Argument passed in is earth Weight.  Calculate weight on each planet:
    double earthWeight = Double.parseDouble(args[0]);
    double mass = earthWeight/pEarth.surfaceGravity();
    for (Planet p : Planet.values())
       System.out.printf("Your weight on %s is %f%n",
                         p, p.surfaceWeight(mass));
}

// Example output:
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
[etc ...]

当前回答

Java枚举实际上是一个完整的类,可以有一个私有构造函数和方法等,而c#枚举只是命名的整数。IMO Java的实现要优越得多。

当你从java营地学习c#时,这个页面应该会对你有很大的帮助。(该链接指向关于枚举的差异(向上/向下滚动查看其他内容)

其他回答

在c#中,属性可以与枚举一起使用。这里是这个编程模式的一个很好的例子,有详细的描述(Codeproject)

public enum Planet
{
   [PlanetAttr(3.303e+23, 2.4397e6)]
   Mercury,
   [PlanetAttr(4.869e+24, 6.0518e6)]
   Venus
} 

编辑:这个问题最近被Jon Skeet再次提出并回答:在c#中,什么相当于Java的enum ? c#中的私有内部类——为什么不经常使用它们?

编辑2:看到公认的答案,它以一种非常聪明的方式扩展了这种方法!

您还可以为每个枚举类型使用一个实用程序类,该类包含每个枚举值的高级数据实例。

public enum Planet
{
    MERCURY,
    VENUS
}

public class PlanetUtil
{
    private static readonly IDictionary<Planet, PlanetUtil> PLANETS = new Dictionary<Planet, PlanetUtil();

    static PlanetUtil()
    {
        PlanetUtil.PLANETS.Add(Planet.MERCURY, new PlanetUtil(3.303e+23, 2.4397e6));
        PlanetUtil.PLANETS.Add(Planet.VENUS, new PlanetUtil(4.869e+24, 6.0518e6));
    }

    public static PlanetUtil GetUtil(Planet planet)
    {
        return PlanetUtil.PLANETS[planet];
    }

    private readonly double radius;
    private readonly double mass;

    public PlanetUtil(double radius, double mass)
    {
        this.radius = radius;
        this.mass = mass;
    }

    // getter
}

Java枚举允许使用编译器生成的valueOf方法从名称进行简单的类型安全转换。

// Java Enum has generics smarts and allows this
Planet p = Planet.valueOf("MERCURY");

c#中等价的raw enum更详细:

// C# enum - bit of hoop jumping required
Planet p = (Planet)Enum.Parse(typeof(Planet), "MERCURY");

但是,如果按照Kent建议的方法,可以很容易地在枚举类中实现ValueOf方法。

我想是这样的:

public class Planets 
{
    public static readonly Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static readonly Planet VENUS = new Planet(4.869e+24, 6.0518e6);
    public static readonly Planet EARTH = new Planet(5.976e+24, 6.37814e6);
    public static readonly Planet MARS = new Planet(6.421e+23, 3.3972e6);
    public static readonly Planet JUPITER = new Planet(1.9e+27,   7.1492e7);
    public static readonly Planet SATURN = new Planet(5.688e+26, 6.0268e7);
    public static readonly Planet URANUS = new Planet(8.686e+25, 2.5559e7);
    public static readonly Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
    public static readonly Planet PLUTO = new Planet(1.27e+22,  1.137e6);
}

public class Planet
{
    public double Mass {get;private set;}
    public double Radius {get;private set;}

    Planet(double mass, double radius)
    {
        Mass = mass;
        Radius = radius;
    }

    // universal gravitational constant  (m3 kg-1 s-2)
    private static readonly double G = 6.67300E-11;

    public double SurfaceGravity()
    {
        return G * Mass / (Radius * Radius);
    }

    public double SurfaceWeight(double otherMass)
    {
        return otherMass * SurfaceGravity();
    }
}

或者像上面那样将常量组合到Planet类中

我怀疑c#中的枚举只是CLR内部的常量,但不是很熟悉它们。我已经在Java中反编译了一些类,我可以告诉你想要的enum是一旦你转换。

Java做了一些狡猾的事情。它将枚举类视为一个普通类,在引用枚举值时使用大量宏。如果在使用枚举的Java类中有case语句,则它将枚举引用替换为整数。如果需要转到string,它会创建一个字符串数组,由它在每个类中使用的序数索引。我猜是为了节省拳击的费用。

如果你下载了这个反编译器,你会看到它如何创建它的类并集成它。说实话,相当吸引人。我过去不使用枚举类,因为我认为它对于一个常量数组来说太臃肿了。比起在c#中有限的使用方式,我更喜欢它。

http://members.fortunecity.com/neshkov/dj.html——Java反编译器