2010-08-09 8 views
19

मुझे लगता है कि, मुझे लगता है कि, एक काफी सरल विधि होना मुश्किल समय है।सी # इन() विधि? (एसक्यूएल की तरह)

मुझे लगता है कि हम सब इस का उपयोग किया है:

select someThing from someTable where someColumn in('item1', 'item2') 

सी # में, मैं इस तरह सामान लिखने की है:

if (someEnum == someEnum.Enum1 || someEnum == someEnum.Enum2 || 
    someEnum == someEnum.Enum3) 
{ 
    this.DoSomething(); 
} 

यह काम करता है, लेकिन यह सिर्फ शब्दों वाले है।

निराशा से, मैंने जो कुछ करने की कोशिश कर रहा हूं उसे पूरा करने के लिए मैंने एक विस्तार विधि लिखा।

namespace System 
{ 
    public static class SystemExtensions 
    { 
     public static bool In<T>(this T needle, params T[] haystack) 
     { 
      return haystack.Contains(needle); 
     } 
    } 
} 

अब, मैं कम कोड लिख सकते हैं:

if (someEnum.In(someEnum.Enum1, someEnum.Enum2, someEnum.Enum3)) 
    this.DoSomething(); 
if (someInt.In(CONSTANT1, CONSTANT2)) 
    this.DoSomethingElse(); 

यह गंदा लगता है, हालांकि, कुछ है कि मैं सिर्फ ढांचे में नहीं मिल सकता है के लिए अपने ही विधि लिखने के लिए।

किसी भी मदद आप लोगों की पेशकश कर सकते महान, धन्यवाद होगा

संपादित करें: धन्यवाद में गहराई से anaylsis के लिए हर किसी को। मुझे लगता है कि मैं अपनी इन() विधि का उपयोग जारी रखूंगा।

+0

विशेष रूप से ऐसा करने के लिए ढांचे में कुछ भी नहीं है, इसलिए आपका दृष्टिकोण ध्वनि लगता है। आप नया [] {someEnum.Enum1, someEnum.Enum2} भी कर सकते हैं। यदि आप एक्सटेंशन विधि नहीं चाहते हैं तो कुछ (कुछ एनीम} शामिल हैं। एक्सटेंशन विधि हालांकि इसे अच्छी तरह से पढ़ती है। – btlog

+3

मैं आमतौर पर 'कंटेनर() ' * इन * प्रश्नों के लिए विस्तार विधि। वास्तव में, लिंक-टू-एसक्यूएल प्रश्नों में 'इन' में 'इन' का अनुवाद होता है।मुझे आपकी 'इन()' एक्सटेंशन विधि पसंद है, क्योंकि यह उपयोग के लिए 'कंटेनस()' के लिए एक अच्छा सिंटैक्टिक रैपर प्रदान करता है जब मेरे पास पहले से ही एक समेकित कंटेनर में मान नहीं होते हैं। – kbrimington

+0

ऐसा लगता है कि आपको बहुत अधिक पता चला है कि एक्सटेंशन विधियां पहले स्थान पर क्यों हैं। मुझे आपके दृष्टिकोण की सफाई पसंद है। –

उत्तर

7

आपके पास मौजूद कोई मौजूदा एक्सटेंशन विधि नहीं है। मुझे समझाएं कि मुझे ऐसा क्यों लगता है (स्पष्ट से अलग "क्योंकि यह निर्दिष्ट नहीं किया गया था, कार्यान्वित, परीक्षण, दस्तावेज, आदि" कारण)।

असल में, यह कार्यान्वयन आवश्यक रूप से अक्षम है। In पर पैरामीटर से एक सरणी का निर्माण (जैसा कि आप params कीवर्ड का उपयोग करते हैं, तब होता है) एक ओ (एन) ऑपरेशन होता है और मुफ्त जीसी दबाव (नए T[] ऑब्जेक्ट के निर्माण से) का कारण बनता है। Contains तब उस सरणी पर गणना करता है, जिसका अर्थ है कि आपका मूल कोड निष्पादन समय में दोगुना से अधिक हो गया है (शॉर्ट-सर्किट मूल्यांकन के माध्यम से एक आंशिक गणना के बजाय, आपको आंशिक गणना के बाद एक पूर्ण गणना मिली है)।

जीसी सरणी निर्माण की वजह से दबाव एक्स भार के प्रकार T के एक्स पैरामीटर 1 से लेने के साथ विस्तार विधि का params संस्करण जहाँ X कुछ उचित संख्या है प्रतिस्थापित करके कुछ हद तक कम किया जा सकता है ... की तरह 1 -2 दर्जन लेकिन यह इस तथ्य को नहीं बदलेगा कि आप एक्स मानों को कॉल स्टैक के नए स्तर पर पास कर रहे हैं, केवल उनसे एक्स से कम जांचने के लिए (यानी, यह प्रदर्शन जुर्माना को खत्म नहीं करता है, केवल इसे कम करता है)।

और फिर एक और मुद्दा है: यदि आप In विस्तार विधि का इरादा रखते हैं तो जंजीर || तुलनाओं के समूह के प्रतिस्थापन के रूप में कार्य करने के लिए, कुछ और है जो आप अनदेखा कर सकते हैं। || के साथ, आपको संक्षिप्त सर्किट मूल्यांकन मिलता है; वही तरीकों से पारित पैरामीटर के लिए नहीं है। एक enum के मामले में, आपके उदाहरण की तरह, इससे कोई फर्क नहीं पड़ता। लेकिन इस कोड पर विचार करें:

if (0 == array.Length || 0 == array[0].Length || 0 == array[0][0].Length) 
{ 
    // One of the arrays is empty. 
} 

ऊपर (अजीब/बुरा - उदाहरण के लिए केवल) कोड एक IndexOutOfRangeException (यह एक NullReferenceException फेंक सकता है, लेकिन उस समय मैं बना रहा हूं के लिए अप्रासंगिक है) फेंक नहीं करना चाहिए। हालांकि, "बराबर" कोड In का उपयोग कर बहुत अच्छी तरह से कर सकते हैं:

if (0.In(array.Length, array[0].Length, array[0][0].Length) 
{ 
    // This code will only be reached if array[0][0].Length == 0; 
    // otherwise an exception will be thrown. 
} 

मैं यह नहीं कह रहा हूँ अपने In विस्तार विचार एक बुरा एक है। ज्यादातर मामलों में, जहां सही तरीके से उपयोग किया जाता है, यह टाइपिंग पर सहेज सकता है और प्रदर्शन/मेमोरी लागत ध्यान देने योग्य नहीं होगी। मैं सिर्फ अपने विचारों की पेशकश कर रहा हूं कि इस तरह की विधि एक अंतर्निहित लाइब्रेरी विधि के रूप में उचित क्यों नहीं होगी: क्योंकि इसकी लागत और सीमाओं को गलत समझा जाएगा, जिससे अधिक उपयोग और उप-कोड कोड हो सकता है।

+0

आप कैसे जानते हैं ओ (एन) है? – mathk

+0

@mathk - ठीक है, अगर आपके पास एन आइटम हैं, तो आपको उन सभी एन आइटम को सरणी में जोड़ना होगा। वस्तुओं को अनदेखा करने का कोई तरीका नहीं है; यदि आप करते हैं, तो आपने परिभाषा के अनुसार सभी एन वस्तुओं की एक सरणी नहीं बनाई है। तो यह कम से कम ओ (एन) होना चाहिए। – jloubert

+0

चूंकि यह एक अपरिवर्तनीय सरणी है, इसलिए आप इसे छोड़कर आइटम को स्थानांतरित करने की आवश्यकता नहीं रख सकते हैं। डोनो कैसे सी # इसे बाहर कर दिया है, लेकिन यह ओ (1) – mathk

0

यदि आप विशेष रूप से Enums के साथ ऐसा करना चाहते हैं तो आपको FlagAttibute में रुचि हो सकती है।

+0

उस विशेषता में केवल कॉस्मेटिक अर्थशास्त्र है। – leppie

+0

@leppie फ्रेमवर्क गणना के ToString कार्यान्वयन में इस विशेषता का उपयोग करता है जब गणनाकर्ता कोई मूल्य नहीं मानता है, और यह दस्तावेज़ के रूप में उपयोगी है। – Trillian

+1

-1 यह बिल्कुल मदद नहीं करेगा। ध्वज विशेषता एक पूरी तरह से ऑर्थोगोनल मुद्दा, अर्थात्, एक एकल चर में एकाधिक enum मानों की संरचना से संबंधित है। ओपी में चर में केवल एक मान है। – siride

0

भाषाएं सभी को खुश नहीं कर सकती हैं, लेकिन क्या आप इसे करते हैं, या संकलक यह करता है कि इसमें कोई अंतर नहीं है। भाषा आप देता है Any & Contains

में अपनी दुनिया में अच्छा हो सकता है, लेकिन यह उन्हें भ्रमित हो जाएगा, जब कोई अन्य व्यक्ति आपके कोड को लेने के लिए है।

1

मुझे लगता है कि आप Contains कॉल का उपयोग कर बंद हैं।

List<strong> items = List<string>{ "item1", "item2", "item3" }; 
bool containsItem = items.Contains("item2"); 

यह लिंक प्रश्नों के लिए आम दृष्टिकोण है।

from item in ... 
where items.contains(item) 
select item 

बीटीडब्ल्यू: मुझे आपकी विस्तार विधि पसंद है, मुझे लगता है कि कुछ स्थितियों में यह बेहद उपयोगी हो सकता है।

+0

वह अपनी विस्तार विधि में कंटेनर का उपयोग कर रहा है। –

1

यह काफी है। आपकी In() विस्तार विधि बहुत अच्छी है। यहां तक ​​कि यदि आप LINQ का उपयोग कर रहे हैं, जिसे SQL के बाद मॉडलिंग किया गया है, तो भी आपको SQL में IN का उपयोग करने का संकेत देने के लिए Contains का उपयोग करना होगा।

from a in table 
where SomeArray.Contains(a.id) 
select a; 

अनुवाद करता है:

select * from table a where a.id in (.....) 
1

मैं और कुछ नहीं पता है।

मेरे लिए, मुझे लगता है कि आपके द्वारा किए जाने वाले संचालन के लिए आपको जितनी बार विस्तार की आवश्यकता है, उतना ही लिखना ठीक है और आप एक पठनीय और आसान वाक्यविन्यास चाहते हैं। यही एक्सटेंशन विधियों के लिए अच्छा है।

आसपास सैकड़ों उपयोगी विस्तार विधियां हैं।आप उनमें से कई के लिए पूछ सकते हैं, वे .NET ढांचे में क्यों शामिल नहीं हैं?

सब कुछ पहले से ही किसी भाषा में शामिल नहीं किया जा सकता है। तो अपनी खुद की लाइब्रेरी लिखें और आशा करें कि इसे भविष्य में शामिल किया जाएगा।

0

अभिव्यक्तियों का उपयोग करके आप कुछ बेहतर कर सकते हैं, यह निर्माण को LINQ2Sql जैसे मामलों में उचित रूप से उपयोग करने की अनुमति देगा।

0

यदि आप अलग-अलग मान लौटाएंगे तो आप इनवर्टर एक्सटेंशन विधि का उपयोग कर सकते हैं। उदाहरण के लिए।

List<string> test = new List<string>() { "1", "2", "2", "3" }; 
List<string> test2 = new List<string>() { "1", "2" }; 

var results = test.Intersect<string>(test2); 
संबंधित मुद्दे