2013-01-09 10 views
15

मैं एक .NET लड़का हूं, इसलिए मुझे पहले कुछ जावा अवधारणाओं की मेरी समझ पर जोर देना चाहिए - अगर मैं गलत हूं तो मुझे सही करें।जावा टाइप क्लास <> के लिए नेट समकक्ष?

class GenericClass< ? extends IInterface> { ... } 

... जो नेट where प्रतिबंध के समान है::

class GenericClass<T> where T: IInterface { ... } 

जावा के Class वर्ग एक प्रकार का वर्णन करता है, और

जावा जेनेरिक्स घिरे वाइल्डकार्ड की अवधारणा का समर्थन लगभग .NET Type वर्ग

0 के समतुल्य है

अब तक, बहुत अच्छा है। लेकिन मुझे सामान्य रूप से Class<T> टाइप किए गए जावा के करीब पर्याप्त समकक्ष नहीं मिल सकता है, जहां टी एक बाध्य वाइल्डकार्ड है। यह मूल रूप से उन प्रकारों पर प्रतिबंध लगाता है जो Class दर्शाते हैं।

मुझे जावा में एक उदाहरण दें।

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 

Assembly assy = GetAssembly();    //unimportant 

Type customClass = assy.GetType(custSortclassName); 
if(!customClass.IsSubclassOf(typeof(IExternalSort))){ 
    throw new InvalidOperationException(...); 
} 
IExternalSort impl = (IExternalSort)Activator.CreateInstance(customClass); 

जावा संस्करण मेरे लिए क्लीनर दिखता है:

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 
Class<? extends IExternalSort> customClass 
    = Class.forName("MyExternalSort") 
     .asSubclass(IExternalSort.class); //this checks for correctness 

IExternalSort impl = customClass.newInstance(); //look ma', no casting! 

निकटतम मैं नेट में मिल सकता है कुछ इस तरह है। क्या .NET समकक्ष को बेहतर बनाने का कोई तरीका है?

+1

यह थोड़ा आसान हो सकता है, लेकिन जहां प्रतिबंध पर 'नई() 'बाधा को जोड़ना संभव नहीं होगा? कुछ 'MyExternalSort : IExternalSort जहां टी: IExternalSort, नया() 'और फिर' var impl = new t();' का उपयोग करें? व्यक्तिगत रूप से मैं ऐसे परिदृश्यों में एक ही इंटरफ़ेस को लागू करने वाले प्रकारों के उदाहरण बनाने के लिए फैक्ट्री पैटर्न का उपयोग करूंगा। – Carsten

+0

मुझे जावा जेनरिक के बारे में बहुत कुछ पता नहीं है, लेकिन मुझे पता है कि वे अलग-अलग लागू किए गए हैं (कोई JVM समर्थन नहीं), और कई चीजों का समर्थन करते हैं जो .NET जेनेरिक नहीं करते हैं। तो – jalf

+0

@Aschratt के लिए सीधे "समतुल्य" खोजने की अपेक्षा न करें Ichratt मैं नहीं देखता कि यह मेरे प्रश्न के लिए प्रासंगिक कैसे है। यह चाल उपयोगी हो सकती है अगर सभी प्रकार की जानकारी संकलन समय पर जानी जाती है, लेकिन MyExternalSort टाइपटाइम तक ज्ञात नहीं है - यह मेरी सॉर्टिंग लाइब्रेरी के क्लाइंट द्वारा अच्छी तरह कार्यान्वित किया जा सकता है, और केवल नाम से निर्दिष्ट है। –

उत्तर

2

विस्तार तरीकों & के लिए एक कस्टम आवरण वर्ग का उपयोग करना System.Type, आप जावा वाक्यविन्यास के बहुत करीब हो सकते हैं।

नोट:Type.IsSubclassOf एक प्रकार एक अंतरफलक को लागू करता है, तो परीक्षण करने के लिए इस्तेमाल नहीं किया जा सकता है - MSDN पर जुड़ा हुआ दस्तावेज़ देखें। इसके बजाय Type.IsAssignableFrom का उपयोग कर सकते हैं - नीचे दिए गए कोड को देखें।

using System; 

class Type<T> 
{ 
    readonly Type type; 

    public Type(Type type) 
    { 
     // Check for the subtyping relation 
     if (!typeof(T).IsAssignableFrom(type)) 
      throw new ArgumentException("The passed type must be a subtype of " + typeof(T).Name, "type"); 

     this.type = type; 
    } 

    public Type UnderlyingType 
    { 
     get { return this.type; } 
    } 
} 

static class TypeExtensions 
{ 
    public static Type<T> AsSubclass<T>(this System.Type type) 
    { 
     return new Type<T>(type); 
    } 
} 

// This class can be expanded if needed 
static class TypeWrapperExtensions 
{ 
    public static T CreateInstance<T>(this Type<T> type) 
    { 
     return (T)Activator.CreateInstance(type.UnderlyingType); 
    } 
} 

इसके अलावा इंटरफ़ेस विचरण का उपयोग कर सुधार

(केवल उत्पादन कोड में उपयोग किया जाना चाहिए के बाद प्रदर्शन का मूल्यांकन किया गया है। एक (समवर्ती!) कैश शब्दकोश ConcurrentDictionary<System.Type, IType<object> का उपयोग करके सुधार किया जा सकता है)

Covariant type parameters का उपयोग करके, सी # 4.0 के साथ पेश की गई एक विशेषता, और एक अतिरिक्त प्रकार interface IType<out T>, जो Type<T> लागू करता है, कोई भी निम्न संभव चीज़ों को बना सकता है:

// IExternalSortExtended is a fictional interface derived from IExternalSort 
IType<IExternalSortExtended> extendedSort = ... 
IType<IExternalSort> externalSort = extendedSort; // No casting here, too. 

एक भी कर सकता है:

using System; 

interface IType<out T> 
{ 
    Type UnderlyingType { get; } 
} 

static class TypeExtensions 
{ 
    private class Type<T> : IType<T> 
    { 
     public Type UnderlyingType 
     { 
      get { return typeof(T); } 
     } 
    } 

    public static IType<T> AsSubclass<T>(this System.Type type) 
    { 
     return (IType<T>)Activator.CreateInstance(
      typeof(Type<>).MakeGenericType(type) 
     ); 
    } 
} 

static class TypeWrapperExtensions 
{ 
    public static T CreateInstance<T>(this IType<T> type) 
    { 
     return (T)Activator.CreateInstance(type.UnderlyingType); 
    } 
} 

ताकि कोई भी कर सकते हैं (स्पष्ट) असंबंधित इंटरफेस InterfaceA और InterfaceB तरह के बीच डाली:

var x = typeof(ConcreteAB).AsSubclass<InterfaceA>(); 
var y = (IType<InterfaceB>)x; 

लेकिन है कि थोड़े अभ्यास का उद्देश्य धरा ।

0

आप "के रूप में" ऑपरेटर का उपयोग एक से थोड़ा खूबसूरत संस्करण प्राप्त कर सकते हैं:

String custSortclassName = GetClassName(); 
Assembly assy = GetAssembly(); 
Type customClass = assy.GetType(custSortclassName); 

IExternalSort impl = Activator.CreateInstance(customClass) as IExternalSort; 
if(impl==null) throw new InvalidOperationException(...); 

लेकिन यहाँ मैं अपने प्रकार है, जो आप के लिए एक मुद्दा हो सकता जाँच से पहले उदाहरण बना रहा हूं।

+1

'as' ऑपरेटर भी एक कलाकार का प्रदर्शन करता है। केवल अंतर यह है कि अगर कलाकार सफल नहीं होता है तो यह अपवाद नहीं फेंकता है। यह वास्तव में इसे आसान नहीं बनाता है। – Carsten

1

सी # जेनेरिक घोषणा-साइट भिन्नता है, एक प्रकार पैरामीटर का भिन्नता तय किया गया है।

जावा, उपयोग साइट भिन्नता है तो एक बार हम एक घोषणा List<E> है, हम इसे 3 तरीके

List<Number>   // invariant, read/write 
List<+Number>   // covariant, read only 
List<-NUmber>   // contravariant, write only 

वहाँ पेशेवरों और दोनों दृष्टिकोण करने के लिए विपक्ष का उपयोग कर सकते हैं। उपयोग-साइट दृष्टिकोण स्पष्ट रूप से अधिक शक्तिशाली है, हालांकि इसे प्रतिष्ठित करने वालों के लिए बहुत मुश्किल माना जाता है। मुझे लगता है कि यह वास्तव में बहुत

List<Integer> integers = ...; 
List<+Number> numbers = integers; // covariant 

दुर्भाग्य से, जावा एक बिल्कुल घृणित वाक्य रचना का आविष्कार किया काबू करने के लिए आसान है,

List<? extends Number> // i.e. List<+Number> 

एक बार अपने कोड इनमें से कई है यह वास्तव में बदसूरत हो जाता है। आपको इसे प्राप्त करना सीखना है।

अब, घोषणा साइट शिविर में, हम एक ही कक्षा में 3 भिन्नताओं को कैसे प्राप्त करते हैं? अधिक प्रकार के साथ - ReadOnlyList<out E>, WriteOnlyList<in E>, और List<E> दोनों को विस्तारित करना। यह बहुत बुरा नहीं है, और कोई कह सकता है कि यह एक बेहतर डिजाइन है। लेकिन अगर अधिक प्रकार के पैरामीटर हैं तो यह बदसूरत हो सकता है। और यदि किसी वर्ग के डिजाइनर ने यह अनुमान नहीं लगाया कि इसे अलग-अलग इस्तेमाल किया जा रहा है, तो वर्ग के उपयोगकर्ताओं के पास इसका उपयोग करने का कोई तरीका नहीं है।

+0

मुझे लगता है कि अब मैं समझता हूं कि आपका उत्तर क्या है - हालांकि यह मेरे [इस (नए) प्रश्न] (http://stackoverflow.com/q/14277441/11545) से अधिक संबंधित है। शायद आप एक नज़र डाल सकते हैं। –

0

आप निम्न जैसा कोई एक्सटेंशन विधि लिखने का प्रयास कर सकते हैं:

static class TypeExtension 
    { 
     public static I NewInstanceOf<I>(this Type t) 
      where I: class 
     { 
      I instance = Activator.CreateInstance(t) as I; 
      if (instance == null) 
       throw new InvalidOperationException(); 
      return instance; 
     } 
    } 

कौन सा तो निम्नलिखित तरीके से इस्तेमाल किया जा सकता:

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 

Assembly assy = GetAssembly(); 
Type customClass = assy.GetType(custSortclassName);    

IExternalSort impl = customClass.NewInstanceOf<IExternalSort>(); 
संबंधित मुद्दे