Od jakiegoś czasu programuję w Javie i właśnie zostałem wrzucony do projektu napisanego całkowicie w języku C #. Próbuję przyspieszyć w C # i zauważyłem wyliczenia używane w kilku miejscach w moim nowym projekcie, ale na pierwszy rzut oka wyliczenia C # wydają się być bardziej uproszczone niż implementacja Java 1.5+. Czy ktoś może wymienić różnice między wyliczeniami C # i Java oraz jak przezwyciężyć różnice? (Nie chcę rozpoczynać wojny z płomieniami językowymi, chcę tylko wiedzieć, jak zrobić pewne rzeczy w języku C #, które robiłem wcześniej w Javie). Na przykład, czy ktoś może opublikować odpowiednik C # do słynnego przykładu enum Planet Słońca?
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 ...]
c#
java
enums
language-comparisons
Ogre Psalm 33
źródło
źródło
Odpowiedzi:
Wyliczenia w CLR są po prostu nazwane stałymi. Typ bazowy musi być integralny. W Javie wyliczenie jest bardziej jak nazwane wystąpienie typu. Ten typ może być dość złożony i - jak pokazuje twój przykład - zawierać wiele pól różnych typów.
Aby przenieść przykład na C #, po prostu zmieniłem wyliczenie na niezmienną klasę i ujawnięłem statyczne instancje tylko do odczytu dla tej klasy:
źródło
W języku C # można zdefiniować metody rozszerzeń w wyliczeniach, co uzupełnia niektóre brakujące funkcje.
Możesz zdefiniować
Planet
jako wyliczenie, a także mieć metody rozszerzenia równoważne dosurfaceGravity()
isurfaceWeight()
.Użyłem niestandardowych atrybutów zgodnie z sugestią Michaiła , ale to samo można osiągnąć za pomocą słownika.
źródło
W języku C # atrybuty mogą być używane z wyliczeniami. Dobry przykład tego schematu programowania ze szczegółowym opisem znajduje się tutaj (Projekt kodowy)
Edycja: to pytanie zostało ostatnio zadane ponownie i odpowiedział Jon Skeet: Jaki jest odpowiednik wyliczenia Java w C #? Prywatne klasy wewnętrzne w języku C # - dlaczego nie są używane częściej?
Edycja 2: zobacz przyjętą odpowiedź, która w bardzo błyskotliwy sposób rozszerza to podejście!
źródło
Wyliczenia Java są w rzeczywistości pełnymi klasami, które mogą mieć prywatnego konstruktora i metody itp., Natomiast wyliczenia C # to tylko liczby całkowite. Implementacja IMO Java jest znacznie lepsza.
Ta strona powinna ci bardzo pomóc w nauce języka c # pochodzącego z obozu java. (Link wskazuje na różnice w wyliczeniach (przewiń w górę / w dół, aby zobaczyć inne rzeczy)
źródło
FOO = 0
która jest łatwiejsza w użyciu w narzędziach ORM (nieordinal()
wymaga użycia podatnego na błędy ). Dalsze C # obsługuje wyliczenia bitowe, które często są bardzo przydatne, szczególnie w połączeniu zEntityFramework
. Java powinna rozszerzyć swoje wyliczenia, aby umożliwić ich powiązanie również z liczbami całkowitymi. Wtedy byliby lepsi :)Myślę, że coś takiego:
Lub połącz stałe w
Planet
klasę jak wyżejźródło
Oto kolejny interesujący pomysł, który uwzględnia niestandardowe zachowanie dostępne w Javie. Wymyśliłem następującą
Enumeration
klasę podstawową:Ma parametr typu w zasadzie tylko po to, aby liczba porządkowa działała poprawnie w różnych wyliczeniach pochodnych.
Operator
Przykład Jona Skeeta z jego odpowiedzi na inne pytanie (http://stackoverflow.com/questions/1376312/whats-the-equivalent-of-javas-enum-in-c) powyżej brzmi:Daje to kilka zalet.
string
i,int
która umożliwia instrukcje zamiany jest możliwaSystem.Enum
można dodać do podstawowej klasy wyliczania, aby umożliwić tę samą funkcjonalność.źródło
właśnie stworzyliśmy rozszerzenie enum dla c # https://github.com/simonmau/enum_ext
To tylko implementacja dla typeafeenum, ale działa świetnie, dlatego stworzyliśmy pakiet do dzielenia się - baw się dobrze
źródło
Wyliczenie Java jest cukrem syntaktycznym służącym do przedstawiania wyliczeń w sposób OO. Są to abstrakcyjne klasy rozszerzające klasę Enum w Javie, a każda wartość enum jest jak statyczna końcowa publiczna implementacja klasy enum. Spójrz na wygenerowane klasy, a dla wyliczenia „Foo” z 10 wartościami zobaczysz wygenerowane klasy „Foo $ 1” do „Foo $ 10”.
Nie znam jednak C #, mogę jedynie spekulować, że wyliczenie w tym języku jest bardziej podobne do tradycyjnego wyliczenia w językach w stylu C. Widzę z szybkiego wyszukiwania Google, że mogą one przechowywać wiele wartości, więc prawdopodobnie są one implementowane w podobny sposób, ale z dużo większymi ograniczeniami niż pozwala na to kompilator Java.
źródło
Wyliczenia Java umożliwiają łatwe konwersje typów z nazwy za pomocą generowanej przez kompilator metody valueOf, tj
Odpowiednik surowego wyliczenia w języku C # jest bardziej szczegółowy:
Jeśli jednak pójdziesz drogą Kentem, możesz łatwo wdrożyć
ValueOf
metodę w klasie enum.źródło
Podejrzewam, że wyliczenia w języku C # są tylko stałymi wewnętrznymi dla CLR, ale nie są tak dobrze z nimi zaznajomione. Zdekompilowałem niektóre klasy w Javie i mogę powiedzieć, że chcesz, aby Enums były konwertowane.
Java robi coś podstępnego. Traktuje klasę wyliczania jako normalną klasę, która, tak blisko, jak to możliwe, używa wielu makr podczas odwoływania się do wartości wyliczania. Jeśli masz instrukcję case w klasie Java, która używa wyliczeń, zastępuje odniesienia wyliczeń do liczb całkowitych. Jeśli potrzebujesz przejść do łańcucha, tworzy on tablicę łańcuchów indeksowanych przez porządek, którego używa w każdej klasie. Podejrzewam, że zaoszczędzę na boksie.
Jeśli pobierzesz ten dekompilator, zobaczysz, jak tworzy on swoją klasę i integruje go. Szczerze mówiąc, fascynujące. Kiedyś nie korzystałem z klasy enum, ponieważ myślałem, że jest ona rozdęta tylko dla szeregu stałych. Podoba mi się to bardziej niż ograniczony sposób używania ich w języku C #.
http://members.fortunecity.com/neshkov/dj.html - Dekompilator Java
źródło
Wyliczanie w Javie jest znacznie bardziej złożone niż wyliczanie w języku C #, a zatem silniejsze. Ponieważ jest to tylko kolejny cukier syntaktyczny w czasie kompilacji, zastanawiam się, czy naprawdę warto było włączyć ten język, biorąc pod uwagę jego ograniczone użycie w rzeczywistych aplikacjach. Czasami trudniej jest trzymać rzeczy z dala od języka niż poddawać się presji, by dołączyć drobne funkcje.
źródło
źródło
Możesz także użyć klasy użyteczności dla każdego typu wyliczenia, która przechowuje instancję z zaawansowanymi danymi dla każdej wartości wyliczenia.
źródło