2009-09-03 4 views
24

सी # में जावा के enum के बराबर क्या है?सी # में जावा के enum के बराबर क्या है?

+2

शायद मैं यह सोच खत्म हो गया हूँ, लेकिन मैं उम्मीद है आप पहले से ही सी # के enum के बारे में पता है और वहाँ जावा के enum जो आप की बात कर रहे के साथ कुछ कार्यक्षमता है। यदि ऐसा है, तो शायद आप अपने प्रश्न में विस्तार कर सकते हैं। –

+8

यदि आप Java 'enum's के बारे में कुछ जानते हैं तो यह प्रश्न पूरी तरह स्पष्ट है। –

+0

@Yishai - सी # enums int32 के लिए डिफ़ॉल्ट है, लेकिन किसी भी संख्यात्मक प्रकार –

उत्तर

34

के बीच पहले वर्णित किया गया है पूर्ण जावा enum कार्यक्षमता सी # में उपलब्ध नहीं है। आप उचित रूप से घोंसले प्रकारों और निजी कन्स्ट्रक्टर का उपयोग करके बंद कर सकते हैं। उदाहरण के लिए:

using System; 
using System.Collections.Generic; 
using System.Xml.Linq; 

public abstract class Operator 
{ 
    public static readonly Operator Plus = new PlusOperator(); 
    public static readonly Operator Minus = 
     new GenericOperator((x, y) => x - y); 
    public static readonly Operator Times = 
     new GenericOperator((x, y) => x * y); 
    public static readonly Operator Divide = 
     new GenericOperator((x, y) => x/y); 

    // Prevent other top-level types from instantiating 
    private Operator() 
    { 
    } 

    public abstract int Execute(int left, int right); 

    private class PlusOperator : Operator 
    { 
     public override int Execute(int left, int right) 
     { 
      return left + right; 
     } 
    } 

    private class GenericOperator : Operator 
    { 
     private readonly Func<int, int, int> op; 

     internal GenericOperator(Func<int, int, int> op) 
     { 
      this.op = op; 
     } 

     public override int Execute(int left, int right) 
     { 
      return op(left, right); 
     } 
    } 
} 
बेशक

आप नेस्टेड प्रकार का उपयोग करने की जरूरत नहीं है, लेकिन वे काम "कस्टम व्यवहार" भाग जो जावा enums के लिए अच्छे हैं दे। अन्य मामलों में आप मूल्यों के एक प्रसिद्ध प्रतिबंधित सेट प्राप्त करने के लिए केवल एक निजी निर्माता को तर्क दे सकते हैं।

  • क्रमसंख्या समर्थन
  • स्विच समर्थन
  • EnumSet
  • क्रमबद्धता/अक्रमांकन (एक सिंगलटन के रूप में)

में से कुछ:

कुछ बातें इस आप नहीं देता जो शायद पर्याप्त प्रयास के साथ किया जा सकता है, हालांकि स्विच हैकरी के बिना वास्तव में संभव नहीं होगा। अब अगर भाषा ऐसा कुछ किया है, तो यह हैकर स्वचालित (जैसे const फ़ील्ड्स का लोड स्वचालित रूप से लोड करके, और enum प्रकार पर किसी भी स्विच को पूर्णांक पर स्विच करने के लिए बदलकर स्विच काम करने के लिए दिलचस्प चीजें कर सकता है, केवल अनुमति देता है "के नाम से" मामलों।)

ओह, और आंशिक प्रकार मतलब है कि आप एक ही फाइल में सभी enum मूल्यों की है की जरूरत नहीं है। यदि प्रत्येक मूल्य काफी शामिल हो जाता है (जो निश्चित रूप से संभव है) प्रत्येक की अपनी फ़ाइल हो सकती है।

+0

मुझे लगता है कि int में अंतर्निहित रूपांतरण का उपयोग करके स्विच स्टेटमेंट (और ordinals) का समर्थन करना मुश्किल होगा, है ना? मैंने क्या अनदेखा किया? –

+2

@ लिमिटेडऑनमेंटमेंट: आप केस एक्सप्रेशन के लिए * स्थिर * मानों का प्रतिनिधित्व कैसे करेंगे? –

+0

मैंने हाल ही में आपके लेख को पढ़ा है कि गैर-निजी फ़ील्ड उचित होने पर कुछ बार ऐसा होता है। क्या यह उन समयों में से एक है? –

-1

enum, या आपको विशेष रूप से कुछ आवश्यक है कि जावा enums है लेकिन C# नहीं है?

+0

जावा में, enums प्रत्येक enum, तर्क के साथ विधियों, और रचनाकारों के लिए कई संबंधित मूल्य हो सकता है। कम से कम सी # 3.0 के रूप में, सी # एनम्स अभी भी संभावित संबंधित मूल्य के साथ स्थिरांक की एक सूची है। –

+6

-1: जावा enums * इतने * सी # वाले से अधिक शक्तिशाली हैं। क्रमी के -1 का मुकाबला करने के लिए – Kramii

+0

+1। सी # एनम्स में एक्सटेंशन विधियां हो सकती हैं जो उन सुविधाओं में से कुछ की अनुपस्थिति के लिए तैयार होती हैं। – finnw

17

Enums कुछ भाषा सुविधाओं में से एक है जो जावा में सी # से बेहतर ढंग से लागू किया गया है। जावा में, enums एक प्रकार के उदाहरण नामित पूर्ण नाम हैं, जबकि सी # enums मूल रूप से स्थिरांक नामित हैं।

कहा जा रहा है कि, मूल मामले के लिए, वे समान दिखेंगे। हालांकि जावा में, आपके पास अधिक शक्ति है, जिसमें आप व्यक्तिगत enums के लिए व्यवहार जोड़ सकते हैं, क्योंकि वे पूर्ण कक्षाएं हैं।

क्या आप विशेष रूप से कुछ विशेषता ढूंढ रहे हैं?

+8

"वे वही काम करेंगे" - आईएमओ नहीं, क्योंकि निरंतर संख्याओं में जावा एनम वैल्यू के विपरीत कस्टम * व्यवहार * नहीं हो सकता है। –

+2

yup, इसलिए 'मूल उपयोग के लिए योग्यता'। मैं मानता हूं कि जावा एनम्स के बारे में अच्छी चीजों में से एक कस्टम व्यवहार – Chi

+1

मुझे सी # एनम्स की तुलना में जावा एनम्स पसंद है। सी # एनम्स के साथ, आप बहुत सारे स्विच स्टेटमेंट्स गंध फैलते हैं, और स्विच कथन में बिखरे हुए इन कोडों में से प्रत्येक कोड को प्रत्येक एनम से जुड़े तरीकों के रूप में रखा जा सकता था। – thenonhacker

4

आप शायद पुराने टाइपएफ़ एनम पैटर्न का उपयोग कर सकते हैं जिसे हमने वास्तविक में प्राप्त करने से पहले जावा में उपयोग किया था (माना जाता है कि सी # में वास्तव में टिप्पणी दावों के रूप में कक्षाएं नहीं हैं)। पैटर्न को this page

+0

+1: एक दृष्टिकोण जिसका मैं उपयोग करता हूं। – Kramii

5

यहां एक और दिलचस्प विचार है। मैं निम्नलिखित Enumeration आधार वर्ग के साथ आया था:

public abstract class Enumeration<T> 
    where T : Enumeration<T> 
{ 
    protected static int nextOrdinal = 0; 

    protected static readonly Dictionary<int, Enumeration<T>> byOrdinal = new Dictionary<int, Enumeration<T>>(); 
    protected static readonly Dictionary<string, Enumeration<T>> byName = new Dictionary<string, Enumeration<T>>(); 

    protected readonly string name; 
    protected readonly int ordinal; 

    protected Enumeration(string name) 
     : this (name, nextOrdinal) 
    { 
    } 

    protected Enumeration(string name, int ordinal) 
    { 
     this.name = name; 
     this.ordinal = ordinal; 
     nextOrdinal = ordinal + 1; 
     byOrdinal.Add(ordinal, this); 
     byName.Add(name, this); 
    } 

    public override string ToString() 
    { 
     return name; 
    } 

    public string Name 
    { 
     get { return name; } 
    } 

    public static explicit operator int(Enumeration<T> obj) 
    { 
     return obj.ordinal; 
    } 

    public int Ordinal 
    { 
     get { return ordinal; } 
    } 
} 

यह एक प्रकार पैरामीटर मिला है मूल रूप से बस इतनी क्रमसूचक गिनती अलग व्युत्पन्न enumerations में ठीक से काम करेंगे।जॉन की Operator उदाहरण तो ऊपर हो जाता है:

public class Operator : Enumeration<Operator> 
{ 
    public static readonly Operator Plus = new Operator("Plus", (x, y) => x + y); 
    public static readonly Operator Minus = new Operator("Minus", (x, y) => x - y); 
    public static readonly Operator Times = new Operator("Times", (x, y) => x * y); 
    public static readonly Operator Divide = new Operator("Divide", (x, y) => x/y); 

    private readonly Func<int, int, int> op; 

    // Prevent other top-level types from instantiating 
    private Operator(string name, Func<int, int, int> op) 
     :base (name) 
    { 
     this.op = op; 
    } 

    public int Execute(int left, int right) 
    { 
     return op(left, right); 
    } 
} 

यह कुछ लाभ प्रदान करता है।

  • क्रमसंख्या समर्थन
  • string करने के लिए रूपांतरण
  • और int जो स्विच बयान संभव बनाता है
  • GetType() एक व्युत्पन्न गणन प्रकार के मूल्यों से प्रत्येक के लिए एक ही परिणाम दे देंगे।
  • System.Enum से स्टेटिक विधियों को समान कार्यक्षमता की अनुमति देने के लिए बेस गणना कक्षा में जोड़ा जा सकता है।
+0

मैं कुछ जावा से सी # रूपांतरण कर रहा हूं इसलिए मैंने एक महीने पहले आपके जवाब को देखा और सोचा कि 'मेरी ज़रूरतों के लिए थोड़ा अधिक परेशानी' है ... अब मैं फिर से वापस आ गया हूं, मुझे बहुत अधिक मूल्य दिख रहा है, जैसा कि मुझे चाहिए '(स्ट्रिंग) नाम' कार्यक्षमता द्वारा enum पुनर्प्राप्त करें। कुडोस! –

+0

@ एंड्रयू कूपर, पुनः: "यह कुछ फायदे देता है। * सामान्य समर्थन * स्ट्रिंग और int में रूपांतरण जो स्विच स्टेटमेंट को व्यवहार्य बनाता है" - ऐसा लगता है कि यह अभी भी स्विच कथन समर्थन नहीं देता है, क्योंकि संकलक शिकायत करता है कि केस स्टेटमेंट को निरंतर मूल्य की आवश्यकता है । यह न तो (int) कास्ट स्वीकार करता है और न ही मूल मूल्य को आधार के रूप में स्वीकार करता है। – tomosius

1
//Review the sample enum below for a template on how to implement a JavaEnum. 
//There is also an EnumSet implementation below. 

public abstract class JavaEnum : IComparable { 
    public static IEnumerable<JavaEnum> Values { 
     get { 
      throw new NotImplementedException("Enumeration missing"); 
     } 
    } 

    public readonly string Name; 

    public JavaEnum(string name) { 
     this.Name = name; 
    } 

    public override string ToString() { 
     return base.ToString() + "." + Name.ToUpper(); 
    } 

    public int CompareTo(object obj) { 
     if(obj is JavaEnum) { 
      return string.Compare(this.Name, ((JavaEnum)obj).Name); 
     } else { 
      throw new ArgumentException(); 
     } 
    } 


    //Dictionary values are of type SortedSet<T> 
    private static Dictionary<Type, object> enumDictionary; 
    public static SortedSet<T> RetrieveEnumValues<T>() where T : JavaEnum { 
     if(enumDictionary == null) { 
      enumDictionary = new Dictionary<Type, object>(); 
     } 
     object enums; 
     if(!enumDictionary.TryGetValue(typeof(T), out enums)) { 
      enums = new SortedSet<T>(); 
      FieldInfo[] myFieldInfo = typeof(T).GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public); 
      foreach(FieldInfo f in myFieldInfo) { 
       if(f.FieldType == typeof(T)) { 
        ((SortedSet<T>)enums).Add((T)f.GetValue(null)); 
       } 
      } 
      enumDictionary.Add(typeof(T), enums); 
     } 
     return (SortedSet<T>)enums; 
    } 
} 


//Sample JavaEnum 
public class SampleEnum : JavaEnum { 
    //Enum values 
    public static readonly SampleEnum A = new SampleEnum("A", 1); 
    public static readonly SampleEnum B = new SampleEnum("B", 2); 
    public static readonly SampleEnum C = new SampleEnum("C", 3); 

    //Variables or Properties common to all enums of this type 
    public int int1; 
    public static int int2 = 4; 
    public static readonly int int3 = 9; 

    //The Values property must be replaced with a call to JavaEnum.generateEnumValues<MyEnumType>() to generate an IEnumerable set. 
    public static new IEnumerable<SampleEnum> Values { 
     get { 
      foreach(var e in JavaEnum.RetrieveEnumValues<SampleEnum>()) { 
       yield return e; 
      } 
      //If this enum should compose several enums, add them here 
      //foreach(var e in ChildSampleEnum.Values) { 
      // yield return e; 
      //} 
     } 
    } 

    public SampleEnum(string name, int int1) 
     : base(name) { 
     this.int1 = int1; 
    } 
} 


public class EnumSet<T> : SortedSet<T> where T : JavaEnum { 
    // Creates an enum set containing all of the elements in the specified element type. 
    public static EnumSet<T> AllOf(IEnumerable<T> values) { 
     EnumSet<T> returnSet = new EnumSet<T>(); 
     foreach(T item in values) { 
      returnSet.Add(item); 
     } 
     return returnSet; 
    } 

    // Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set. 
    public static EnumSet<T> ComplementOf(IEnumerable<T> values, EnumSet<T> set) { 
     EnumSet<T> returnSet = new EnumSet<T>(); 
     foreach(T item in values) { 
      if(!set.Contains(item)) { 
       returnSet.Add(item); 
      } 
     } 
     return returnSet; 
    } 

    // Creates an enum set initially containing all of the elements in the range defined by the two specified endpoints. 
    public static EnumSet<T> Range(IEnumerable<T> values, T from, T to) { 
     EnumSet<T> returnSet = new EnumSet<T>(); 
     if(from == to) { 
      returnSet.Add(from); 
      return returnSet; 
     } 
     bool isFrom = false; 
     foreach(T item in values) { 
      if(isFrom) { 
       returnSet.Add(item); 
       if(item == to) { 
        return returnSet; 
       } 
      } else if(item == from) { 
       isFrom = true; 
       returnSet.Add(item); 
      } 
     } 
     throw new ArgumentException(); 
    } 

    // Creates an enum set initially containing the specified element(s). 
    public static EnumSet<T> Of(params T[] setItems) { 
     EnumSet<T> returnSet = new EnumSet<T>(); 
     foreach(T item in setItems) { 
      returnSet.Add(item); 
     } 
     return returnSet; 
    } 

    // Creates an empty enum set with the specified element type. 
    public static EnumSet<T> NoneOf() { 
     return new EnumSet<T>(); 
    } 

    // Returns a copy of the set passed in. 
    public static EnumSet<T> CopyOf(EnumSet<T> set) { 
     EnumSet<T> returnSet = new EnumSet<T>(); 
     returnSet.Add(set); 
     return returnSet; 
    } 

    // Adds a set to an existing set. 
    public void Add(EnumSet<T> enumSet) { 
     foreach(T item in enumSet) { 
      this.Add(item); 
     } 
    } 

    // Removes a set from an existing set. 
    public void Remove(EnumSet<T> enumSet) { 
     foreach(T item in enumSet) { 
      this.Remove(item); 
     } 
    } 
}