2015-09-06 9 views
28

मैं इस कोड है (पूरे कोड महत्वपूर्ण नहीं है लेकिन this link पर देखा जा सकता):LINQ विधि का उपयोग करते समय सी # कंपाइलर निजी प्रदर्शन क्लास क्यों बनाता है() और मैं इससे कैसे बच सकता हूं?

internal static class PlayCardActionValidator 
{ 
    public static bool CanPlayCard(...) 
    { 
     // ... 
     var hasBigger = 
      playerCards.Any(
       c => c.Suit == otherPlayerCard.Suit 
        && c.GetValue() > otherPlayerCard.GetValue()); 
     // ... 
    } 
} 

उदाहरण के लिए decompiler (ILSpy) में कोड खोलने के बाद मैं द्वारा नव निर्मित कक्षा <>c__DisplayClass0_0 के अस्तित्व पर ध्यान सी # संकलक:

enter image description here

यह नहीं करता है, तो इस कोड प्रणाली के प्रदर्शन के लिए महत्वपूर्ण नहीं था मेरे लिए एक समस्या होगी। इस विधि लाखों बार कहा जाता है और कचरा कलेक्टर इन <>c__DisplayClass0_0 उदाहरण हैं जिनमें प्रदर्शन को धीमा कर देती सफाई है:

enter image description here

का उपयोग करते समय मैं इस वर्ग (उसके उदाहरणों और उनके कचरा एकत्र करने) बनाने बच सकते हैं Any विधि?

सी # कंपाइलर इस वर्ग को क्यों बनाता है और क्या Any() का कोई विकल्प है जिसका उपयोग मैं कर सकता हूं?

+4

यह कब्जा कर लिया चर के लिए एक सुरक्षित घर खोजने के लिए अपने कोड को फिर से लिखने की जरूरत है, otherPlayerCard और यहाँ ट्रम्पकार्ड। उन्हें स्थानीय चर से फ़ील्ड में बदलना ताकि उनका मूल्य विधि निकाय से परे संरक्षित किया जा सके। DisplayClass वह सुरक्षित घर है। –

+11

हॉट पथ पर LINQ का उपयोग न करें, यह Roslyn codebase पर नीति है। – DaveShaw

+5

मैं आमतौर पर सूक्ष्म अनुकूलन की सिफारिश करने से बचूंगा, लेकिन यदि यह कोड ** लाखों ** बार चलाया जा रहा है, तो इसे गति के लिए अनुकूलित करने के लिए इसे पुन: सक्रिय करना यहां समाधान होगा। LINQ धीमा है। –

उत्तर

36

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

... बेशक कि जादू जैसी कोई चीज़ नहीं है। उस राज्य को वास्तव में कहीं वास्तविक रहना है, कहीं कहीं बंद करने की विधि से जुड़ा हुआ है और आसानी से उपलब्ध है। और आप प्रोग्रामिंग पैटर्न को क्या कहते हैं जहां आप सीधे एक या अधिक तरीकों से राज्य को जोड़ते हैं?

यह सही है: कक्षाएं। कंपाइलर लैम्ब्डा को क्लोजर क्लास में बदल देता है, फिर होस्टिंग विधि के अंदर कक्षा को तुरंत चालू करता है ताकि होस्टिंग विधि कक्षा में राज्य तक पहुंच सके।

ऐसा करने का एकमात्र तरीका बंद होने का उपयोग नहीं करना है। यदि यह वास्तव में प्रदर्शन को प्रभावित कर रहा है, तो LINQ अभिव्यक्ति के बजाय पुराने स्कूल FOR लूप का उपयोग करें।

+11

_ "कोई भी पर्याप्त उन्नत तकनीक जादू से अलग नहीं है।" _ - आर्थर सी क्लार्क – Gusdor

23

किसी भी विधि का उपयोग करते समय मैं इस वर्ग (उनके उदाहरण और उनके कचरा संग्रहण) बनाने से कैसे बच सकता हूं?

सी # कंपाइलर इस वर्ग को क्यों बनाता है और क्या कोई भी विकल्प है() मैं इसका उपयोग कर सकता हूं?

अन्य पोस्टर पहले से ही क्यों हिस्सा बताया गया है, इसलिए बेहतर सवाल होगा मैं एक बंद के निर्माण कैसे बच सकते हैं?। और जवाब सरल है: यदि लैम्ब्डा का उपयोग कर रहा है तो पास पैरामीटर और/या स्थिरांक, कंपाइलर बंद नहीं करेगा। उदाहरण के लिए:

bool AnyClub() { return playerCards.Any(c => c.Suit == CardSuit.Club); } 

bool AnyOf(CardSuit suit) { return playerCards.Any(c => c.Suit == suit); } 

पहला दूसरा बंद होने पर बंद नहीं होगा।

सब इसे ध्यान में रखते

, और यह सोचते हैं आप छोरों के लिए/foreach का उपयोग नहीं करना चाहते, तो आप System.Linq.Enumerable में लेकिन अतिरिक्त पैरामीटर के साथ उन लोगों के लिए इसी तरह खुद का विस्तार तरीकों बना सकते हैं। इस विशेष मामले के लिए, कुछ इस तरह काम करेगा:

public static class Extensions 
{ 
    public static bool Any<T, TArg>(this IEnumerable<T> source, TArg arg, Func<T, TArg, bool> predicate) 
    { 
     foreach (var item in source) 
      if (predicate(item, arg)) return true; 
     return false; 
    } 
} 

और करने के लिए प्रश्न में कोड बदलने के लिए:

var hasBigger = 
    playerCards.Any(otherPlayerCard, 
     (c, opc) => c.Suit == opc.Suit 
      && c.GetValue() > opc.GetValue()); 
+1

एचएम, पैरामीटर या इंस्टेंस सदस्यों के लिए बंद क्यों नहीं किया जाएगा? मुझे पता नहीं है कि इसे खींचा जा सकता है। – usr

+0

@usr यह एक स्थिर/आवृत्ति समारोह बनाएगा और इसमें एक प्रतिनिधि को बांध देगा। एक अलग वर्ग की आवश्यकता नहीं है क्योंकि पूरे राज्य में तर्क और/या 'यह' शामिल है। –

+0

ठीक है, कक्षा के लिए कोई ज़रूरत नहीं है। यह सच है। लेकिन कक्षा में शून्य perf प्रभाव है। ताजा प्रतिनिधि और बंद करने के उदाहरण बनाना महंगा है। मेरा मानना ​​है कि सवाल perf के बारे में है। वह छिपे हुए वर्ग के बारे में चिंतित नहीं है। – usr

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

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