2010-01-03 10 views
15

मैं काम पर कोडर्स में जोशुआ ब्लोच के साथ एक साक्षात्कार पढ़ रहा था, जहां उन्होंने जावा 5 में जेनरिक के परिचय को शोक व्यक्त किया। उन्हें विशिष्ट कार्यान्वयन पसंद नहीं है क्योंकि भिन्नता-जावा के वाइल्डकार्ड-इसे अनावश्यक रूप से जटिल बनाते हैं।सी # जेनेरिक - डिजाइन द्वारा कम सीमा के बिना?

जहां तक ​​मुझे पता है, सी # 3 में स्पष्ट, बाध्य वाइल्डकार्ड जैसे कुछ भी नहीं है, उदा। आप एक विधि PriceBatch घोषित नहीं कर सकते हैं जो संपत्ति या किसी भी संपत्ति उपclass (void PriceBatch(Collection<? extends Asset> assets) जावा में) का संग्रह एकत्र करता है?)।

क्या किसी को पता है कि वाइल्डकार्ड और सीमाएं सी # में क्यों नहीं शामिल की गई हैं? क्या इन सुविधाओं को जानबूझकर भाषा को सरल बनाने के लिए छोड़ दिया गया था, या यह ऐसा कुछ है जिसे वे अभी तक लागू करने के लिए नहीं मिला है?

संपादित करें: पवित्र धुआं, एरिक लिपर्ट से खुद की टिप्पणियां! उसके और पॉल व्यावहारिक टिप्पणियां पढ़ने के बाद, मुझे लगता है कि कम से कम ऊपरी सीमा का समर्थन कर रहे एहसास है और ऊपर के उदाहरण सी # करने के लिए अनुवाद किया जा सकता है कि के रूप में:

void PriceBatch<T>(ICollection<T> assets) where T : Asset 

निचले सीमा, दूसरे हाथ पर, जाहिरा तौर पर एरिक के रूप में समर्थित नहीं हैं अपनी दूसरी टिप्पणी में कहते हैं, उदाहरण के लिए

public class Asset {} 
public class Derivative extends Asset {} 
public class VanillaOption extends Derivative {} 

public static <T extends Asset> void copyAssets(Collection<T> src, Collection<? super T> dst) { 
    for(T asset : src) dst.add(asset); 
} 

Collection<VanillaOption> src = new ArrayList<VanillaOption>(); 
[...] 
Collection<Derivative> dst = new ArrayList<Derivative>(); 
[...] 
copyAssets(src, dst); 

मैं सही हूँ: वहाँ शायद कोई रास्ता सीधे सी # करने के लिए इस (कुछ काल्पनिक) जावा कोड का अनुवाद करने में है? यदि यह मामला है, तो क्या कोई विशेष कारण है कि सी # ऊपरी है लेकिन कम सीमा नहीं है?

+5

मैं सवाल समझ में नहीं आता; सी # ने जेनेरिकों को बाध्य किया है और सी # के बाद से है। क्या आप उस जावा पर प्राप्त कर रहे हैं * कॉल-साइट * कॉन्वर्सिस और निर्मित जेनेरिक प्रकारों पर contravariance? क्योंकि सी # इसका समर्थन नहीं करता है; सी # 4 * घोषणा-साइट * भिन्नता का समर्थन करेगा। –

+6

या आप इस तथ्य पर क्या प्राप्त कर रहे हैं कि जेनेरिक तरीकों पर पैरामीटर सीमाएं केवल सीमाओं से प्राप्त होनी चाहिए, और सीमा से प्राप्त नहीं होना चाहिए? सी # उत्तरार्द्ध का समर्थन नहीं करता है; जावा और स्कैला मुझे विश्वास है। –

+0

धन्यवाद, मैंने प्रश्न अपडेट किया है। – ehnmark

उत्तर

20

एक जटिल सवाल।

सबसे पहले अपने मौलिक प्रश्न पर विचार करें, "यह सी # में अवैध क्यों है?"

class C<T> where T : Mammal {} // legal 
class D<T> where Giraffe : T {} // illegal 

यही है, एक सामान्य प्रकार बाधा कह सकते हैं" टी किसी भी संदर्भ प्रकार है कि प्रकार स्तनपायी के एक चर को सौंपा जा सकता है, जिनमें से एक चर होना चाहिए ", लेकिन नहीं" टी किसी भी संदर्भ प्रकार होना चाहिए एक जिराफ सौंपा जा सकता है "। अंतर क्यों?

मुझे नहीं पता। यह सी # टीम पर मेरे समय से बहुत पहले था। मामूली जवाब" क्योंकि सीएलआर इसका समर्थन नहीं करता है ", लेकिन टीम जो सी # जेनेरिक डिजाइन किया गया था एक ही टीम जो सीएलआर जेनेरिक डिजाइन करती है, इसलिए यह वास्तव में एक स्पष्टीकरण नहीं है।

मेरा अनुमान बस इतना ही होगा कि एक सुविधा का समर्थन करने के लिए ग्राहकों को डिज़ाइन, कार्यान्वित, परीक्षण, दस्तावेज और भेजना होगा; इस सुविधा के लिए किसी ने कभी भी इनमें से कोई भी काम नहीं किया है, और इसलिए यह भाषा में नहीं है। मुझे प्रस्तावित सुविधा के लिए एक बड़ा, आकर्षक लाभ नहीं दिख रहा है; जटिल सुविधाओं के साथ जटिल सुविधाओं को यहां चारों ओर काट दिया जाता है।

हालांकि, यह अनुमान है। अगली बार जब मैं जेनेरिक पर काम करने वाले लोगों के साथ चैट करना चाहता हूं - वे इंग्लैंड में रहते हैं, इसलिए ऐसा नहीं लगता कि वे मेरे हॉल से नीचे हैं, दुर्भाग्य से - मैं पूछूंगा।

आपके विशिष्ट उदाहरण के लिए, मुझे लगता है कि पॉल सही है। सी # में उस काम को करने के लिए आपको कम बाध्य बाधाओं की आवश्यकता नहीं है। आप कह सकते हैं:

void Copy<T, U>(Collection<T> src, Collection<U> dst) where T : U 
{ 
    foreach(T item in src) dst.Add(item); 
} 

है, टी पर, यू पर नहीं बाधा डाल

+1

फॉलो-अप के लिए धन्यवाद।पुस्तक प्रभावी जावा एक परिदृश्य बताती है जहां यह उपयोगी होगा: कहें कि आप एक प्रकार 'MyStack ' को एक विधि 'पॉपएल'' के साथ परिभाषित करते हैं जो गंतव्य संग्रह को पैरामीटर के रूप में लेता है। यदि आपके पास 'MyStack ' है, तो आप इसकी वस्तुओं को 'सूची ' पर कॉपी करने में सक्षम होना चाहिए, लेकिन यह व्यक्त करने के लिए कि आपको सार्वजनिक शून्य 'पॉपएल (आईसीओलेक्शन डीएसटी) जैसे कुछ कहना होगा, जहां टी: एक्स' और यह वास्तव में अवैध लगता है। – ehnmark

+7

हाँ, यह उपयोगी होगा। दिलचस्प बात यह है कि सी # में आप सीधे ऐसा नहीं कर सकते हैं, आप * स्टैक पर एक विस्तार विधि बनाकर कर सकते हैं! यह एक नया प्रकार पैरामीटर पेश करता है जिसे तब बाधित किया जा सकता है। –

+0

एक और उदाहरण जो मैं देख सकता था 'सिस्टम' चयन में 'IImmutableList ' का संविधान होगा। चयन। Immutable'; वर्तमान में, 'IImmutableList जोड़ें (टी आइटम) 'इसे रोकता है, लेकिन एक' IImmutableList जोड़ें (TNew आइटम) जहां TNew: T' इसे सहेज लेगा। (ठीक है, इसलिए अपरिवर्तनीय इंटरफ़ेस को शुरू करने के लिए शुरू करने योग्य इंटरफ़ेस को कार्यान्वित नहीं किया जाएगा, लेकिन मुझे लगता है कि उनके पास उस डिज़ाइन के साथ जाने का कारण था।) यहां, एक्सटेंशन विधियां आपको अब तक नहीं मिलेंगी। – fuglede

8

सी # 4 नई विशेषताएं पेश करता है जो जेनेरिक में कॉन्वर्सिस और contravariance की अनुमति देता है।

अन्य अतः पदों कि और अधिक विस्तार में इस बारे में बात कर रहे हैं: How is Generic Covariance & Contra-variance Implemented in C# 4.0?

नई सुविधा सभी प्रकार में स्वचालित रूप से इसे सक्षम नहीं है, लेकिन वहाँ एक नया वाक्य रचना कि डेवलपर्स सामान्य तर्क हैं तय करने के लिए अनुमति देता है कॉन्वर्सेंट या contravariant।

सी # 4 से पहले सी # संस्करणों की समान कार्यक्षमता थी क्योंकि यह प्रतिनिधियों और कुछ सरणी प्रकारों से संबंधित थी। प्रतिनिधियों के संबंध में, आधार पैरामीटर प्रकारों में लेने वाले प्रतिनिधियों की अनुमति है। सरणी प्रकारों के संबंध में, मुझे लगता है कि यह वैध है जब तक कि मुक्केबाजी शामिल न हो। यही है, ग्राहक की एक सरणी वस्तु की सरणी के मामले में हो सकती है। हालांकि, चींटियों की एक सरणी को वस्तुओं की एक सरणी में नहीं डाला जा सकता है।

+0

Arrays भी: स्ट्रिंग [] भी एक वस्तु है []। – codekaizen

+0

मेरा उत्तर अपडेट किया गया, धन्यवाद। – Eilon

+2

उत्परिवर्ती संग्रह/सरणी गैर-संस्करण होना चाहिए। अन्यथा यह प्रकार की सुरक्षा तोड़ता है। –

7

पहले से ही वाइल्डकार्ड के बराबर है नेट, अधिक तार्किक नामित सामान्य प्रकार की कमी है, तो आप आप क्या वर्णन कोई समस्या नहीं के साथ 2

namespace ConsoleApplication3 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ICollection<VanillaOption> src = new List<VanillaOption>(); 
     ICollection<Derivative> dst = new List<Derivative>(); 
     copyAssets(src, dst); 
     } 

     public static void copyAssets<T,G>(ICollection<T> src, ICollection<G> dst) where T : G { 
      foreach(T asset in src) 
       dst.Add(asset); 
     } 
    } 
    public class Asset {} 
    public class Derivative : Asset {} 
    public class VanillaOption : Derivative {} 
} 

इस उदाहरण का प्रतिनिधित्व करता है क्या कर सकते हैं

namespace ConsoleApplication3 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
     List<a> a = new List<a>(); 
     List<b> b = new List<b>(); 
     List<c> c = new List<c>(); 
     test(a); 
     test(b); 
     test(c); 

     } 

     static void test<T>(List<T> a) where T : a 
     { 
      return; 
     } 
    } 
    class a 
    { 

    } 
    class b : a 
    { 

    } 
    class c : b 
    { 

    } 
} 

उदाहरण जावा में आपके उदाहरण से एक कोड रूपांतरण।

हालांकि मैं वास्तव में वास्तविक प्रश्न का उत्तर देने की स्थिति में नहीं हूं!

+0

हाय पॉल, एक प्रश्न: आपके कोड उदाहरण का निहितार्थ यह है कि "जहां टी: ए" में व्यक्त सामान्य बाधा ... तथ्य के आधार पर यह न केवल "ए" का एक उदाहरण "संभाल" करेगा, लेकिन , भी, कोई ऑब्जेक्ट अवरुद्ध, कोई फर्क नहीं पड़ता कि "ए" से "परोक्ष रूप से" कैसे: जावा में जेनेरिक में वाइल्डकार्ड के बराबर है? बस अपने फायदे के लिए स्पष्टीकरण की मांग; निहित या इरादे से आपके उत्तर की कोई आलोचना नहीं है। तथ्य यह है कि "ए" के पत्र में आपके उदाहरण में तीन अलग-अलग अर्थ (वर्ग, आंतरिक चर, और पैरामीटर नाम) हैं, जो मेरे लिए ग्रोक करने के लिए कठिन बनाते हैं, fyi। – BillW

+0

हां, यह थोड़ा अस्पष्ट है, क्षमा चाहता है। मैंने आपके निचले बाध्य कोड का एक उदाहरण लिखा है, कार्यात्मक रूप से यह वही है, लेकिन यह कम सीमाओं का उपयोग नहीं करता है! –

+0

हाय पॉल और आपके अपडेट किए गए उत्तर के लिए धन्यवाद। मेरा सवाल वास्तव में है कि क्यों सी # 3 में इस संबंध में जावा के भिन्न समर्थन का सबसेट है और क्या यह जावा "गलत" करने के लिए "सही" करने का एक जानबूझकर निर्णय है, या सीएलआर सीमाओं या क्या नहीं है। कम सीमाएं उपयोगी होने पर एक सार्थक उदाहरण खोजना मुश्किल होता है, क्योंकि मेरा योगदान उदाहरण दिखाता है, और शायद यह उत्तर का हिस्सा है :) – ehnmark

संबंधित मुद्दे