2013-02-14 99 views
14

लागू करने पर LINQ भ्रमित हो जाता है मेरी कक्षा IEnumerable<T> दो बार लागू करती है। मैं LINQ को hashtable कास्टिंग किए बिना काम करने के लिए कैसे प्राप्त कर सकता हूं?IEQumerable <T> को दो बार


मैं अपने खुद के covariant hashtable कार्यान्वयन वह भी नेट के IDictionary<TKey, TValue> से विरासत में लिखा था। आखिरकार, T के लिए यह विभिन्न प्रकार के साथ IEnumerable<T> दो बार लागू करता है। मैंने प्राथमिक गणनाशील इंटरफेस को निहित रूप से लागू किया, और दूसरा स्पष्ट रूप से लागू किया। इस (स्यूडोकोड) की तरह कुछ:

class HashTable<TKey, TValue> : 
    ... 
    IEnumerable<out IAssociation<out TKey, out TValue>>, 
    IEnumerable<out KeyValuePair<TKey, TValue>> 
{ 
    // Primary: 
    public IEnumerator<IAssociation<TKey, TValue>> GetEnumerator(); 
    // Secondary: 
    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator(); 
} 

जब मैं हैश तालिका foreach, यह as expected प्राथमिक गणनीय लेता है:

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

var hashtable = new HashTable<string, int>(); 
foreach (var kv in hashtable) 
{ 
    // kv is IAssociation<string, int> 
} 

अब मैं इसे LINQ में एक ही बात करना चाहता हूँ, लेकिन यह flings मुझ पर संकलक त्रुटियों क्योंकि यह पता नहीं है जो इंटरफ़ेस विस्तार के तरीकों के लिए लेने के लिए:

var xs1 = from x in hashtable   // <-- 1 
      select x; 

var xs2 = hashtable.Select(x => x); // <-- 2 

त्रुटि 1: स्रोत प्रकार 'हैशटेबल' के लिए क्वेरी पैटर्न का कार्यान्वयन नहीं मिला। 'चयन' नहीं मिला। सीमा चर 'x' के प्रकार को स्पष्ट रूप से निर्दिष्ट करने पर विचार करें।

त्रुटि 2: 'हैशटेबल' में 'चयन' की परिभाषा नहीं है और 'हैशटेबल' प्रकार के पहले तर्क को स्वीकार करने के लिए कोई भी विस्तार विधि 'चयन' नहीं मिल सकती है (क्या आप एक निर्देश या असेंबली संदर्भ का उपयोग कर रहे हैं?)

शायद कुछ इंटरफ़ेस या विरासत चाल है जिसके बारे में मुझे पता नहीं है?

using SCG = System.Collections.Generic; 

public class HashTable<TKey, TValue> 
    : IKeyedCollection<TKey, TValue>, SCG.IDictionary<TKey, TValue> 

public interface IKeyedCollection<out TKey, out TValue> 
    : ICollection<IAssociation<TKey, TValue>> 

public interface ICollection<out T> : SCG.IEnumerable<T> 

public interface IAssociation<out TKey, out TValue> 

// .NET Framework: 
public interface IDictionary<TKey, TValue> 
    : ICollection<KeyValuePair<TKey, TValue>> 

public interface ICollection<T> 
    : IEnumerable<T> 

अब आप देख सकते हैं कि मैं क्यों KeyValuePair<TKey, TValue> और IAssociation<TKey, TValue> ही नहीं कर सके:


जो लोग पूछा के लिए, यहाँ इंटरफेस का पूरा पेड़ है।

+4

क्या आपने मैन्युअल रूप से 'चयन' के [जेनेरिक तर्क] (http://msdn.microsoft.com/en-GB/library/bb548891.aspx) निर्दिष्ट करने का प्रयास किया है? लगता है कि उन्हें परेशान करने में परेशानी हो रही है। विशेष रूप से, आपको मैन्युअल रूप से 'टीएसओआरएस' निर्दिष्ट करने की आवश्यकता है, लेकिन एक बार जब आप एक करते हैं, तो आपको दोनों को ऐसा करने की ज़रूरत है। दुर्भाग्यवश, यह आपको कुछ परेशान कामकाज के बिना अनाम प्रकारों को वापस करने से रोक देगा। –

+0

क्या आप 'हैशटेबल <टीके, टीवीएयू> 'के लिए शेष विरासत/इंटरफेस शामिल कर सकते हैं? –

+1

वैसे यह आपको बताता है कि कम से कम पहली त्रुटि के बारे में क्या करना है। आपको स्पष्ट रूप से कहना होगा कि 'x' किस प्रकार है: IAssociation x हैशटेबल में x का चयन करें x; – Stonehead

उत्तर

24

यह समझना महत्वपूर्ण है कि किसी विधि कॉल के लिए तर्क के रूप में अभिव्यक्ति का उपयोग करने के दौरान संकलक में "प्राथमिक" और "माध्यमिक" इंटरफ़ेस कार्यान्वयन की कोई अवधारणा नहीं है। आपका प्रकार IEnumerable<IAssociation<...>> और IEnumerable<KeyValuePair<...>> दोनों समान रूप से अच्छी तरह से लागू करता है, जहां तक ​​उन प्रकार के रूपांतरणों का संबंध है। यही कारण है कि संकलक को अधिक जानकारी चाहिए।

public IEnumerable<IAssociation<TKey, TValue>> Associations { get { return this; } } 
public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return this; } } 

इसका मतलब है कि तुम सच में आसानी से विशिष्ट हो सकता है:

सरल दृष्टिकोण (IMO) दो नए गुणों को पेश किया जाएगा

var query = from x in table.Associations 
      ...; 

या

var query = from x in table.KeyValuePairs 
      ...; 

नहीं केवल यह मदद संकलक को खुश रखने में मदद करता है - यह कोड को पढ़ने की कोशिश करने में भी किसी की भी मदद करेगा।यदि आपको लगता है कि आप इनमें से अधिक अन्य में से एक का उपयोग करते हैं, तो आप हमेशा HashTable बना सकते हैं केवल एक ही IEumerable<> लागू करें और अन्य संपत्ति टाइप करें और रखें।

+0

के साथ जाऊंगा, मुझे यह जवाब बहुत पसंद है। –

+0

क्या आपके कंपाइलर को सीधे लागू करने के माध्यम से संतुष्ट करने का कोई अन्य तरीका नहीं है। – antonijn

+1

@ एंटोनिजन: हां, आप प्रकार तर्कों को स्पष्ट रूप से निर्दिष्ट करके संकलक को संतुष्ट कर सकते हैं ... –

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

  • कोई संबंधित समस्या नहीं^_^