2011-12-15 14 views
19

IOrderedEnumerable को अर्थपूर्ण मूल्य के लिए पूरी तरह से वापसी प्रकार के रूप में उपयोग किया जाना चाहिए?IOrderedEnumerable वापस कब?

उदाहरण के लिए, प्रस्तुति परत में एक मॉडल का उपभोग करते समय, हम कैसे जान सकते हैं कि संग्रह को आदेश देने की आवश्यकता है या पहले से ही आदेश दिया गया है?

इस मामले में क्या एक भंडार ORDER BY खंड के साथ संग्रहीत प्रक्रिया को लपेटता है। क्या भंडार IOrderedEnumerable लौटाएगा? और यह कैसे हासिल किया जाएगा?

+0

यह संभव डुप्लिकेट देख http://stackoverflow.com/questions/829487/c-is-it-possible-to-return-an-iorderedenumerablet या http://stackoverflow.com/questions/1783830/can -यह-हो-लाभप्रद के लिए एक-विधि-टू-वापसी-iorderedenumerablet-बजाय के- मैं? RQ = 1 – nawfal

उत्तर

17

मुझे नहीं लगता कि यह एक अच्छा विचार हो सकता है है:

चाहिए IOrderedEnumerable अर्थ मूल्य के लिए विशुद्ध रूप से टाइप वापसी के रूप में इस्तेमाल किया जा सकता है?

उदाहरण के लिए, प्रस्तुति परत में एक मॉडल का उपभोग करते समय, हम कैसे जान सकते हैं कि संग्रह को आदेश देने की आवश्यकता है या पहले से ही आदेश दिया गया है?

यह जानने में क्या बात है कि अनुक्रम का आदेश दिया गया है यदि आपको पता नहीं है कि किस कुंजी का आदेश दिया गया है? IOrderedEnumerable इंटरफ़ेस का बिंदु द्वितीयक प्रकार के मानदंडों को जोड़ने में सक्षम होना है, जो आपको नहीं समझता है कि यदि आप प्राथमिक मानदंड क्या नहीं जानते हैं।

इस मामले में क्या एक भंडार संग्रहित प्रक्रिया को ऑर्डर द्वारा ऑर्डर के साथ लपेटता है। क्या रिपॉजिटरी वापस IOrderedEnumerable वापसी चाहिए? और यह कैसे हासिल किया जाएगा?

यह समझ में नहीं आता है। जैसा कि मैंने पहले ही कहा है, IOrderedEnumerable का उपयोग द्वितीयक प्रकार के मानदंडों को जोड़ने के लिए किया जाता है, लेकिन जब संग्रहीत प्रक्रिया द्वारा डेटा वापस किया जाता है, तो यह पहले से ही क्रमबद्ध होता है और माध्यमिक प्रकार मानदंड जोड़ने में बहुत देर हो चुकी है। आप जो भी कर सकते हैं वह पूरी तरह से इसे फिर से क्रमबद्ध कर रहा है, इसलिए परिणाम पर ThenBy पर कॉल करने से अपेक्षित प्रभाव नहीं होगा।

+0

यह जरूरी नहीं कि माध्यमिक तरह मानदंड जोड़ने के लिए बहुत देर हो चुकी।() 'पर आधारित है कि एक बहुत ही सामान्य तरीके से ऐसा करने के लिए, लेकिन यह एक विधि को पता था कि यह हमेशा पर क्षेत्र' A' आदेश 'पेशकश करने के लिए CreateOrderedEnumerable हैं के लिए संभव हो जाएगा - यह बहुत कठिन है - शायद असंभव की बात करने के ज्ञान (जो 'फिर से' कॉल करता है)। हालांकि अधिक सामान्य मामले में बहुत अधिक कठिन, और शायद वास्तव में बहुत उपयोगी नहीं है। –

8

जैसा कि थॉमस बताता है कि एक वस्तु IOrderedEnumerable हमें बताती है कि इसे किसी भी तरह से आदेश दिया गया है, न कि यह आदेश दिया गया है कि हम इसे बनाए रखना चाहते हैं।

यह भी ध्यान देने योग्य बात है कि वापसी प्रकार ओवरराइड को प्रभावित करने और संकलन की क्षमता होगी, लेकिन चेक के क्रम नहीं लायक है:

private static IOrderedEnumerable<int> ReturnOrdered(){return new int[]{1,2,3}.OrderBy(x => x);} 
private static IEnumerable<int> ReturnOrderUnknown(){return ReturnOrdered();}//same object, diff return type. 
private static void UseEnumerable(IEnumerable<int> col){Console.WriteLine("Unordered");} 
private static void UseEnumerable(IOrderedEnumerable<int> col){Console.WriteLine("Ordered");} 
private static void ExamineEnumerable(IEnumerable<int> col) 
{ 
    if(col is IOrderedEnumerable<int>) 
    Console.WriteLine("Enumerable is ordered"); 
    else 
    Console.WriteLine("Enumerable is unordered"); 
} 
public static void Main(string[] args) 
{ 
    //Demonstrate compile-time loses info from return types 
    //if variable can take either: 
    var orderUnknown = ReturnOrderUnknown(); 
    UseEnumerable(orderUnknown);//"Unordered"; 
    orderUnknown = ReturnOrdered(); 
    UseEnumerable(orderUnknown);//"Unordered" 
    //Demonstate this wasn't a bug in the overload selection: 
    UseEnumerable(ReturnOrdered());//"Ordered"' 
    //Demonstrate run-time will see "deeper" than the return type anyway: 
    ExamineEnumerable(ReturnOrderUnknown());//Enumerable is ordered. 
} 
इस वजह से

, यदि आप एक मामला है जहां या तो IEnumerable<T> या IOrderedEnumerable<T> लौटे हो सकता है परिस्थिति के आधार पर कॉलर को, चर को IEnumerable<T> के रूप में टाइप किया जाएगा और रिटर्न प्रकार की जानकारी खो दी जाएगी। इस बीच, कोई फर्क नहीं पड़ता कि रिटर्न प्रकार क्या है, कॉलर यह निर्धारित करने में सक्षम होगा कि यह प्रकार वास्तव में IOrderedEnumerable<T> है या नहीं।

किसी भी तरह से, वापसी का प्रकार वास्तव में कोई फर्क नहीं पड़ता।

रिटर्न प्रकारों के साथ व्यापार-बंद कॉलर बनाम कॉलर बनाम लचीलापन के बीच उपयोगिता के बीच है।

वर्तमान में return currentResults.ToList() के साथ समाप्त होने वाली विधि पर विचार करें।निम्नलिखित वापसी प्रकार संभव हो रहे हैं:

  1. List<T>
  2. IList<T>
  3. ICollection<T>
  4. IEnumerable<T>
  5. IList
  6. ICollection
  7. IEnumerable
  8. object

की वस्तु और गैर सामान्य प्रकार अभी बाहर निकालने के रूप में उपयोगी होने की संभावना नहीं हैं (मामलों में जहां वे उपयोगी होगा में, वे शायद नहीं brainer निर्णय उपयोग करने के लिए कर रहे हैं)। इस पत्ते:

  1. List<T>
  2. IList<T>
  3. ICollection<T>
  4. IEnumerable<T>

सूची हम चले उच्च ऊपर, अधिक सुविधा हम फोन करने वाले उजागर कार्यक्षमता का उपयोग करने के लिए दे उस प्रकार से, यह नीचे दिए गए प्रकार से अवगत नहीं है। हम जिस सूची में जाते हैं, उतनी ही कम लचीलापन हम भविष्य में कार्यान्वयन को बदलने के लिए कैली को अधिक लचीलापन देते हैं। आदर्श रूप में, हम सूची के उच्चतम के रूप में जाना चाहते हैं क्योंकि विधि के उद्देश्य के संदर्भ में समझ में आता है (कॉलर को उपयोगी कार्यक्षमता का पर्दाफाश करने के लिए, और ऐसे मामलों को कम करें जहां नए संग्रह बनाए गए हैं जो हम पहले से ही पेशकश कर रहे थे) लेकिन कोई उच्च नहीं (भविष्य में बदलाव की अनुमति देने के लिए)।

तो, वापस हमारे मामले के लिए जहां हम एक IOrderedEnumerable<TElement> है कि हम के रूप में वापसी कर सकते हैं या तो एक IOrderedEnumerable<TElement> या एक IEnumerable<T> (या IEnumerable या object)।

सवाल यह है कि यह वास्तव में विधि के उद्देश्य से संबंधित IOrderedEnumerable है, या यह केवल एक कार्यान्वयन आर्टेफैक्ट है?

अगर हम था एक विधि ReturnProducts क्योंकि कॉल करने की परवाह नहीं करनी चाहिए कि यह है कि, कीमत से ऑर्डर करने के लिए के लिए निकालने से मामलों के कार्यान्वयन जहां एक ही उत्पाद अलग-अलग मूल्य के लिए दो बार पेशकश की गई थी के भाग के रूप, तो यह IEnumerable<Product> लौट जाना हुआ आदेश दिया, और निश्चित रूप से इस पर निर्भर नहीं होना चाहिए।

हम एक विधि ReturnProductsOrderedByPrice जहां आदेश अपने उद्देश्य का हिस्सा था था, तो हम IOrderedEnumerable<Product> लौटना चाहिए, क्योंकि इस अपने उद्देश्य के लिए और अधिक बारीकी से संबंधित है, और यथोचित अपेक्षा कर सकते हैं कि केवल बुला CreateOrderedEnumerable, ThenBy या ThenByDescending उस पर (चीजें जो वास्तव में प्रदान करती हैं) और कार्यान्वयन में बाद में बदलाव से यह टूट नहीं गया है।

संपादित करें: मुझे इसका दूसरा भाग याद आया।

इस मामले में एक भंडार क्लॉज द्वारा ऑर्डर द्वारा संग्रहीत प्रक्रिया को लपेटता है। क्या रिपॉजिटरी वापस IOrderedEnumerable वापसी चाहिए? और यह कैसे प्राप्त किया जाएगा?

यह संभव होने पर काफी अच्छा विचार है (या शायद IOrderedQueryable<T>)। हालांकि, यह आसान नहीं है।

सबसे पहले, आपको यह सुनिश्चित करना होगा कि ORDER BY के बाद कुछ भी आदेश को पूर्ववत नहीं कर सकता था, यह मामूली नहीं हो सकता है।

दूसरे, आप CreateOrderedEnumerable<TKey>() के लिए एक कॉल में इस आदेश को वापस नहीं ला करने के लिए है।

उदाहरण के लिए, खेतों A, B, C और D साथ तत्वों कुछ है कि ORDER BY A DESCENDING, B इस्तेमाल किया एक प्रकार है कि IOrderedEnumerable<El> लागू करता MyOrderedEnumerable<El> कहा जाता है की वापसी में जिसके परिणामस्वरूप से लौटे कर रही है। फिर, तथ्य यह है कि A और B वे फ़ील्ड हैं जिन्हें ऑर्डर किया गया था जिन्हें संग्रहीत किया जाना चाहिए। CreateOrderedEnumerable(e => e.D, Comparer<int>.Default, false) पर कॉल (जो ThenBy और ThenByDescending कॉल भी है) उन तत्वों के समूह लेना चाहिए जो समान रूप से A और B के लिए समान नियमों के साथ तुलना करते हैं, जिसके लिए वे डेटाबेस द्वारा लौटाए गए थे (डेटाबेस और .NET के बीच मेलिंग मिलान कठिन), और केवल उन समूहों के भीतर यह cmp.Compare(e0.D, e1.D) के अनुसार आदेश देना चाहिए।

यदि आप ऐसा कर सकते हैं, तो यह बहुत उपयोगी हो सकता है, और यह पूरी तरह उपयुक्त होगा कि IOrderedEnumerableORDER BY क्लॉज सभी कॉलों द्वारा उपयोग किए जाने वाले सभी प्रश्नों पर मौजूद होंगे।

अन्यथा, IOrderedEnumerable झूठ होगा - क्योंकि आप इसे प्रदान किए गए अनुबंध को पूरा नहीं कर पाएंगे - और यह बेकार से कम होगा।

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