2008-12-02 20 views
25

क्या आपके पास एक डिफ़ॉल्ट प्रकार है जिसे आप LINQ प्रश्नों के परिणामों के साथ अपने लेनदेन में उपयोग करना पसंद करते हैं?क्या आप ToList() करते हैं?

डिफ़ॉल्ट रूप से LINQ IEnumerable<> या शायद IOrderedEnumerable<> लौटाएगा। हमने पाया है कि List<> आम तौर पर हमारे लिए अधिक उपयोगी है, इसलिए हमारे कार्यों में ToList() की अधिकांश आदतों को अपनाया गया है, और निश्चित रूप से List<> हमारे फ़ंक्शन तर्क और वापसी मूल्यों में उपयोग कर रहा है।

इसका एकमात्र अपवाद LINQ से SQL में रहा है जहां .ToList() पर कॉलिंग IEnumerable समय-समय पर गणना करेगी।

हम भी डब्ल्यूसीएफ का व्यापक रूप से उपयोग कर रहे हैं, डिफ़ॉल्ट संग्रह प्रकार System.Array है। हम अपने शेष कोडबेस के साथ स्थिरता के लिए VS2008 में सेवा संदर्भ सेटिंग्स संवाद में हमेशा इसे System.Collections.Generic.List में बदलते हैं।

आप क्या करते हैं?

उत्तर

23

ToListहमेशा तुरंत अनुक्रम का मूल्यांकन करता है - न केवल LINQ से SQL में। यदि आप इसे चाहते हैं, तो यह ठीक है - लेकिन यह हमेशा उपयुक्त नहीं है।

व्यक्तिगत रूप से मैं यह घोषणा करने से बचने की कोशिश करता हूं कि आप List<T> सीधे लौटते हैं - आमतौर पर IList<T> अधिक उपयुक्त है, और बाद में आपको एक अलग कार्यान्वयन में बदलने की अनुमति देता है। बेशक, कुछ ऑपरेशन हैं जो केवल List<T> पर ही निर्दिष्ट हैं ... इस प्रकार का निर्णय हमेशा मुश्किल होता है।

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

+1

सहमत हैं कि ToList तुरंत मूल्यांकन करता है। हमारी सोच यह है कि LINQtoSQL में इसका प्रदर्शन प्रभाव होने की संभावना है (विशेष रूप से यदि हम कुछ LINQ अभिव्यक्तियों को एक साथ जोड़ रहे हैं), लेकिन जब हम स्मृति में हों तो कोई भी प्रदर्शन हिट लापरवाही होगी - और मनुष्यों के लिए स्थिरता अधिक है जरूरी। –

+3

प्रदर्शन से परे महत्वपूर्ण अंतर हैं। विशेष रूप से, यदि क्वेरी के बारे में कुछ भी (जैसे स्रोत में डेटा) बदलता है, तो स्थगित निष्पादन आपको एक अलग उत्तर देगा। कभी-कभी आप यही चाहते हैं, कभी-कभी यह नहीं होता है। –

2

यह निर्भर करता है कि आपको संग्रह को संशोधित करने की आवश्यकता है या नहीं। मुझे एक ऐरे का उपयोग करना पसंद है जब मुझे पता है कि कोई भी आइटम जोड़ने/हटाने जा रहा है। जब मैं आइटम को सॉर्ट/एड/डिलीट करने की आवश्यकता होती हूं तो मैं एक सूची का उपयोग करता हूं। लेकिन, आमतौर पर जब तक मैं कर सकता हूं, मैं इसे केवल आईनेमरेबल के रूप में छोड़ देता हूं।

16

हमारे पास एक ही परिदृश्य है - सर्वर पर डब्ल्यूसीएफ संचार, सर्वर LINQtoSQL का उपयोग करता है।

हम सर्वर से ऑब्जेक्ट्स का अनुरोध करते समय .ToArray() का उपयोग करते हैं, क्योंकि क्लाइंट सूची बदलने के लिए यह "अवैध" है। (मतलब, "अजीब" का समर्थन करने का कोई उद्देश्य नहीं है, "। निकालें", आदि)।

हालांकि सर्वर पर अभी भी, मैं अनुशंसा करता हूं कि आप इसे डिफ़ॉल्ट के रूप में छोड़ दें (जो IENumerable नहीं है, बल्कि IQueryable है)। इस तरह, यदि आप कुछ मानदंडों के आधार पर और भी फ़िल्टर करना चाहते हैं, तो मूल्यांकन करने तक SQL पक्ष पर फ़िल्टरिंग STILL है।

यह एक बहुत ही महत्वपूर्ण बात है क्योंकि इसका मतलब यह है कि आप जो भी करते हैं उसके आधार पर अविश्वसनीय प्रदर्शन लाभ या हानि का मतलब है।

उदाहरण:

// This is just an example... imagine this is on the server only. It's the 
// basic method that gets the list of clients. 
private IEnumerable<Client> GetClients() 
{ 
    var result = MyDataContext.Clients; 

    return result.AsEnumerable(); 
} 

// This method here is actually called by the user... 
public Client[] GetClientsForLoggedInUser() 
{ 
    var clients = GetClients().Where(client=> client.Owner == currentUser); 

    return clients.ToArray(); 
} 

आप देखते हैं कि वहाँ क्या हो रहा है?"GetClients" विधि डेटाबेस से सभी 'क्लाइंट' के डाउनलोड को मजबूर करने जा रही है ... फिर यह फ़िल्टर करने के लिए GetClientsForLoogedInUser विधि में कहां होगा।

private IQueryable<Client> GetClients() 
{ 
    var result = MyDataContext.Clients; 

    return result.AsQueryable(); 
} 

अब, वास्तविक मूल्यांकन नहीं होगा जब तक ".ToArray" कहा जाता है ... और SQL छानने करना होगा:

अब, मामूली परिवर्तन की सूचना। काफी बेहतर!

+0

आपका पॉइंट एक बहुत ही विशिष्ट है। हालांकि ज्यादातर लोग इसे याद करते हैं। मैं वास्तव में इस तरह के खराब उदाहरण देखता हूं। लोग इस बारे में सोचना बंद नहीं करते कि निष्पादन पर वह कास्ट क्या करने जा रहा है। –

+0

महान उत्तर, बहुत स्पष्ट। बहुत बहुत धन्यवाद – MegaMind

7

लिंक-टू-ऑब्जेक्ट्स मामले में, List<T> फ़ंक्शन से लौटने पर IList<T> लौटने के समान अच्छा नहीं है, क्योंकि वेनेरबल स्केट बताते हैं। लेकिन अक्सर आप उससे भी बेहतर कर सकते हैं। यदि आप जिस चीज को लौट रहे हैं उसे अपरिवर्तनीय होना चाहिए, तो IList एक खराब विकल्प है क्योंकि यह कॉलर को चीजों को जोड़ने या हटाने के लिए आमंत्रित करता है।

उदाहरण के लिए, कभी-कभी आपके पास एक विधि या संपत्ति होती है जो एक लिंक क्वेरी का परिणाम देता है या yield return का उपयोग आलसी रूप से एक सूची उत्पन्न करने के लिए करता है, और फिर आप महसूस करते हैं कि पहली बार ऐसा करना बेहतर होगा , List<T> में परिणाम कैश करें और उसके बाद कैश किए गए संस्करण को वापस करें। ऐसा तब होता है जब IList लौटने का एक बुरा विचार हो सकता है, क्योंकि कॉलर अपने उद्देश्यों के लिए सूची को संशोधित कर सकता है, जो तब आपके कैश को दूषित कर देगा, जिससे अन्य सभी कॉलर्स में उनके परिवर्तन दिखाई दे सकते हैं।

IEnumerable<T> वापस करने के लिए बेहतर है, इसलिए उनके पास आगे बढ़ना है। और यदि कॉलर तेजी से यादृच्छिक पहुंच चाहता है, यानी वे चाहते हैं कि वे इंडेक्स तक पहुंचने के लिए [] का उपयोग कर सकें, तो वे ElementAt का उपयोग कर सकते हैं, जो लिंक परिभाषित करता है ताकि यह चुपचाप IList के लिए स्नीफ हो और यदि उपलब्ध हो तो इसका उपयोग करता है, और यदि यह गूंगा नहीं है रैखिक लुकअप

एक बात मैंने ToList का उपयोग किया है, जब मुझे कस्टम ऑपरेटरों के साथ मिश्रित लिंक अभिव्यक्तियों की एक जटिल प्रणाली मिली है जो सूचियों को फ़िल्टर या बदलने के लिए yield return का उपयोग करती है। डीबगर में कदम उठाने से शक्तिशाली भ्रमित हो सकता है क्योंकि यह आलसी मूल्यांकन करने के आसपास कूदता है, इसलिए मैं कभी-कभी अस्थायी रूप से कुछ स्थानों पर एक टोस्टिस्ट() जोड़ता हूं ताकि मैं निष्पादन पथ का अधिक आसानी से अनुसरण कर सकूं। (यद्यपि यदि आप जिन चीजों को निष्पादित कर रहे हैं, वे दुष्प्रभाव हैं, यह प्रोग्राम के अर्थ को बदल सकता है।)

+0

यह भी ध्यान रखें कि .NET 4.5 में वास्तव में पढ़ने के लिए एक लोकप्रिय आंदोलन है जो लोकप्रिय इंटरफेस प्रदान करता है जिसे हम नए आईरेडऑनलिस्ट के साथ आईलीस्ट जैसे प्यार करने के लिए उभरे हैं। http://msdn.microsoft.com/en-us/library/hh192385.aspx – jpierson

2

यदि आपको सूची <> की अतिरिक्त विशेषताओं की आवश्यकता नहीं है, तो क्यों न केवल IQueryable <> के साथ चिपके रहें? !?!?! सबसे कम आम denominator सबसे अच्छा समाधान है (विशेष रूप से जब आप तीमुथियुस के जवाब देखते हैं)।

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