IComparable <T> Vs. का उपयोग कब करें IComparer <टी>


101

मैं यह पता लगाने की कोशिश कर रहा हूं कि मुझे इनमें से कौन सा इंटरफेस लागू करना है। वे दोनों अनिवार्य रूप से एक ही काम करते हैं। मैं कब एक का उपयोग करूंगा?


महान उदाहरण और स्पष्टीकरण यहाँ पाए जाते हैं: support.microsoft.com/nl-nl/help/320727/…
Jan

जवाबों:


96

वैसे वे एक ही तरह की चीज़ नहीं हैं जो IComparer<T>एक प्रकार पर लागू की जाती हैं जो दो अलग-अलग वस्तुओं की तुलना करने में सक्षम है जबकि IComparable<T>उन प्रकारों पर लागू किया जाता है जो एक ही प्रकार के अन्य उदाहरणों के साथ खुद की तुलना करने में सक्षम हैं।

मैं ऐसे समय के लिए उपयोग IComparable<T>करना चाहता हूं जब मुझे यह जानने की आवश्यकता होती है कि एक और उदाहरण किस तरह से संबंधित है this। तुलना के बाहर के IComparer<T>रूप में संग्रह को छांटने के लिए उपयोगी है IComparer<T>


9
IComparer <T> आपको प्रत्येक प्रकार के लिए एक वर्ग रखने की अनुमति भी देता है। उदाहरण; PersonLastFirstNameComparer, PersonFirstLastNameComparer, या PersonAgeComparer।
एरिक श्नाइडर

क्या उन्हें याद रखने के लिए कोई आसान तरीका है? मैं इसे हर बार देखना चाहता हूं।
अमादिब

59
@ दामाद को लगता है IComparableकि मैं तुलनीय हूं । जिसका अर्थ है कि मेरी तुलना किसी और चीज से की जा सकती है। और मैं एक तुलना कर रहा हूँ केIComparer रूप में पढ़ा , मैं बस तुलना जो मैं कुछ चीजों की तुलना का मतलब है।
नवफाल

@newfal आपको इसे उत्तर के रूप में रखना चाहिए था। मुझे लगता है कि यह यहाँ की सबसे अच्छी व्याख्या है।
जीन एस

42

IComparable<T>जब कक्षा में आंतरिक तुलना हो तो प्रयोग करें ।

का प्रयोग करें IComparer<T>जब आप कक्षा 'आंतरिक तुलना के अलावा किसी अन्य तुलना विधि चाहते हैं, तो यह एक है।


28

यह इकाई पर निर्भर करता है। उदाहरण के लिए "स्टूडेंट" जैसे वर्ग के लिए, यह नाम के आधार पर IComparable का अर्थ होगा।

class Student : IComparable 
{
    public string Name { get; set; }
    public int MathScore { get; set; }
    public int EnglishScore { get; set; }

    public int TotalScore 
    {
        get
        {
            return this.MathScore + this.EnglishScore; 
        }
    }

    public int CompareTo(object obj)
    {
        return CompareTo(obj as Student);  
    }

    public int CompareTo(Student other)
    {
        if (other == null)
        {
            return 1;
        }
        return this.Name.CompareTo(other.Name);  
    }
}

लेकिन अगर एक शिक्षक 'ए' मैथ्सकोर के आधार पर छात्रों की तुलना करना चाहता है, और शिक्षक 'बी' इंग्लिशकोर के आधार पर छात्रों की तुलना करना चाहता है। IComparer को अलग से लागू करना अच्छा रहेगा। (एक रणनीति पैटर्न की तरह)

class CompareByMathScore : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        if (x.MathScore > y.MathScore)
          return 1;
        if (x.MathScore < y.MathScore)
          return -1;
        else
          return 0;
    }
}

उपयोग की आसानी के लिए तुलना विधि को स्थिर बनाएं ।
Jan

9

यह सब इस बात पर निर्भर करता है कि आपका प्रकार पारस्परिक है या नहीं। आपको केवल गैर-परस्पर प्रकारों पर IComparable को लागू करना चाहिए । ध्यान दें कि यदि आप IComparable को लागू करते हैं, तो आपको ==,! =; <और> ऑपरेटरों (कोड विश्लेषण चेतावनी CA1036 देखें) के साथ, समतुल्य को ओवरराइड करना होगा।

इस ब्लॉग पोस्ट से डेव जी का उद्धरण :

लेकिन सही उत्तर यह है कि अगर आपकी वस्तुएं परस्पर हैं, तो IComparable के बजाय IComparer को लागू करना है, और आवश्यक होने पर फ़ंक्शन को सॉर्ट करने के लिए IComparer का एक उदाहरण पास करें।

चूँकि IComparer उस समय उस स्थान पर छँटाई के लिए उपयोग की जाने वाली एक डिस्पोजेबल वस्तु है, इसलिए आपकी वस्तु में आपकी इच्छा के अनुसार कोई भी परिवर्तनशील शब्दार्थ हो सकता है। इसके अलावा, इसकी आवश्यकता नहीं है या यहां तक ​​कि इक्वल्स, गेटहैशकोड, या == का उपयोग करने का सुझाव भी है - आप इसे कृपया किसी भी तरह से परिभाषित करने के लिए स्वतंत्र हैं।

अंत में, आप विभिन्न क्षेत्रों पर या अलग-अलग नियमों के आधार पर अपने प्रकार के लिए कई IComparer को परिभाषित कर सकते हैं। यह एक परिभाषा के साथ अटक जाने की तुलना में बहुत अधिक लचीला है।

संक्षेप में: संदर्भ प्रकारों के लिए मूल्य प्रकार और IComparer के लिए IComparable का उपयोग करें।


6

एक कहानी के माध्यम से सरल व्याख्या

हाई स्कूल बास्केटबॉल। यह टीमों के लिए एक स्कूल यार्ड पिक है। मैं अपनी टीम में सबसे लंबे / सबसे अच्छे / सबसे तेज़ लोगों को प्राप्त करना चाहता हूं। मैं क्या करूं?

IComparer Interface - दो लोगों की तुलना अलग-अलग लोगों से करें

  • यह मुझे किसी भी दो लोगों की तुलना करने की अनुमति देता है ......... यह मूल रूप से है। फ्रेड बनाम जॉन .......... मैंने उन्हें एक ठोस वर्ग में फेंक दिया जो इंटरफ़ेस को लागू करता है। Compare(Fred, John)और यह पता चला है कि कौन बेहतर है।

IComparable के बारे में क्या? - अपनी तुलना किसी और से करें

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

  • हम वर्तमान उदाहरण (स्वयं) की तुलना किसी अन्य ऑब्जेक्ट (किसी और) के साथ कर रहे हैं जो एक ही प्रकार (व्यक्ति) का है।

तुलना वर्ग के बारे में क्या?

तुलनात्मक वर्ग एक सार आधार वर्ग है जो IComparer इंटरफ़ेस को लागू करता है। आपको इस वर्ग से एक ठोस कार्यान्वयन प्राप्त करना चाहिए। वैसे भी, Microsoft अनुशंसा करता है कि आप IComparer इंटरफ़ेस को लागू करने के बजाय तुलना वर्ग का उपयोग करें:

हम अनुशंसा करते हैं कि आप IComparer इंटरफ़ेस को लागू करने के बजाय तुलनाकर्ता वर्ग से प्राप्त करें, क्योंकि Comparer वर्ग IComparer.Compare विधि का एक स्पष्ट इंटरफ़ेस कार्यान्वयन प्रदान करता है और डिफ़ॉल्ट गुण जो ऑब्जेक्ट के लिए डिफ़ॉल्ट तुलनित्र प्राप्त करता है।

सारांश

  • IComparer - दो चीजों की तुलना करें और तुलना करें।
  • अमूर्त - एफबी पर दूसरों के साथ अपनी तुलना करें।

आशा है कि कहानियाँ आपको याद रखने में मदद करेंगी।


1
मुझे कुंजी अवधारणा को दर्शाने का आपका तरीका पसंद है। यदि आप इस प्रतियोगिता में तुलना (टी) वर्ग को शामिल करते हैं तो बेहतर हो सकता है। यहां तक ​​कि यह प्रश्न में शामिल नहीं है। :)
केवमैन

4

जैसा कि दूसरों ने कहा है, वे एक ही काम नहीं करते हैं।

किसी भी मामले में, इन दिनों मैं IComparer का उपयोग नहीं करते हैं। यही कारण है कि मैं? इसकी ज़िम्मेदारी (दो वस्तुओं की तुलना करने के लिए इस्तेमाल की जाने वाली एक बाहरी इकाई) को लैम्ब्डा अभिव्यक्ति के साथ बहुत क्लीनर के रूप में संभाला जा सकता है, जो कि LINQ के अधिकांश तरीकों के समान है। एक त्वरित लैम्ब्डा लिखें जो वस्तुओं को तर्क के रूप में तुलना करने के लिए लेता है, और एक बूल लौटाता है। और अगर ऑब्जेक्ट अपने स्वयं के आंतरिक तुलना ऑपरेशन को परिभाषित करता है, तो इसके बजाय IComparable को लागू कर सकता है।


1
-1: एक बूल लौटाना IComparer के बराबर नहीं है। IComparer एक मान देता है जो शून्य / शून्य से कम / शून्य से अधिक हो सकता है और आमतौर पर छँटाई के लिए उपयोग किया जाता है।
जो

और जब आपकी आवश्यकता होती है, तो आप इसके बजाय एक इंट (या बेहतर अभी भी, एक एनम) लौटाते हैं। क्या यह वास्तव में एक बड़ी बात है?
jalf

2
आप एक बूल भी वापस कर सकते हैं, क्योंकि एक क्रम को क्रमबद्ध करने के लिए आपको केवल एक ही ऑपरेशन की आवश्यकता होती है।
jalf

एक IComparer कार्यान्वयन को केवल एक बार परिभाषित करने की आवश्यकता है, यदि आपको अधिक स्थानों में छंटनी तर्क का उपयोग करने की आवश्यकता है, तो लंबोदर अभिव्यक्ति को अधिक बार लिखना होगा।
o

o - फिर आप उस प्रतिनिधि के लिए एक संदर्भ संग्रहीत कर सकते हैं जिसे एक लंबोदर अभिव्यक्ति के रूप में लिखा गया था और इसे फिर से उपयोग किया जाता है।
3

3

IComparable का कहना है कि एक वस्तु की दूसरे के साथ तुलना की जा सकती है। IComparer एक ऐसी वस्तु है जो किसी भी दो वस्तुओं की तुलना कर सकती है।


2

IComparer एक इंटरफ़ेस है जो Array को सॉर्ट करने के लिए उपयोग किया जाता है, यह इंटरफ़ेस क्लास को तुलना (T x, T y) विधि को लागू करने के लिए मजबूर करेगा, जो दो वस्तुओं की तुलना करेगा। जिस वर्ग ने इस इंटरफ़ेस को लागू किया है उसका उदाहरण एरे की छँटाई में उपयोग किया जाता है।

IComparable एक इंटरफ़ेस है जिसे उस प्रकार में लागू किया जाता है जिसमें एक ही प्रकार की दो वस्तुओं की तुलना करने की आवश्यकता होती है, यह तुलनीय इंटरफ़ेस क्लास को निम्न विधि को लागू करने के लिए मजबूर करेगा। तुलना (T obj)

IEqualityComparer एक इंटरफ़ेस है जिसका उपयोग ऑब्जेक्ट को खोजने के लिए किया जाता है कि क्या यह समान है या नहीं, अब हम इसे एक नमूने में देखेंगे जहां हमें किसी संग्रह में ऑब्जेक्ट की डिस्टिक्ट को ढूंढना होगा। यह इंटरफ़ेस एक विधि को लागू करेगा बराबर (T obj1, T obj2)

अब हम एक उदाहरण लेते हैं हमारे पास एक कर्मचारी वर्ग है, इस वर्ग के आधार पर हमें एक संग्रह बनाना है। अब हमारी निम्नलिखित आवश्यकताएं हैं।

सरणी श्रेणी का उपयोग करके ऐरे को क्रमबद्ध करें 2. Linq का उपयोग करके एक संग्रह की आवश्यकता है: डुप्लिकेट निकालें, उच्चतर से आदेश कम करें, एक कर्मचारी आईडी निकालें

abstract public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { set; get; }
}

public enum SortType
{
    ByID,
    BySalary
}

सार्वजनिक वर्ग EmployeeIdSorter: IComparer {सार्वजनिक int तुलना (कर्मचारी x, कर्मचारी y) {अगर (x.Id <y.Id) वापसी 1; और अगर (x.Id> y.Id) रिटर्न -1; और वापसी 0; }}

    public class EmployeeSalarySorter : IComparer<Employee>
    {
        public int Compare(Employee x, Employee y)
        {
            if (x.Salary < y.Salary)
                return 1;
            else if (x.Salary > y.Salary)
                return -1;
            else
                return 0;
        }
    }

अधिक जानकारी के लिए नीचे देखें http://dotnetvisio.blogspot.in/2015/12/usage-of-icomparer-icomparable-and.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.