কীভাবে আইকুয়ালিটি কম্পিউটার ব্যবহার করবেন


98

আমার ডাটাবেসে একই নম্বর সহ কিছু ঘন্টা রয়েছে। আমি তাদের সকলকে নকল ছাড়াই পেতে চাই। আমি এই কাজটি করার জন্য একটি তুলনামূলক ক্লাস তৈরি করেছি, তবে ফাংশনটি সম্পাদনটি 0.6 সেকেন্ড থেকে 3.2 সেকেন্ড থেকে আলাদা ছাড়াই ফাংশন থেকে বড় বিলম্বের কারণ ঘটায়!

আমি কি এটি সঠিকভাবে করছি বা আমাকে অন্য কোনও পদ্ধতি ব্যবহার করতে হবে?

reg.AddRange(
    (from a in this.dataContext.reglements
     join b in this.dataContext.Clients on a.Id_client equals b.Id
     where a.date_v <= datefin && a.date_v >= datedeb
     where a.Id_client == b.Id
     orderby a.date_v descending 
     select new Class_reglement
     {
         nom  = b.Nom,
         code = b.code,
         Numf = a.Numf,
     })
    .AsEnumerable()
    .Distinct(new Compare())
    .ToList());

class Compare : IEqualityComparer<Class_reglement>
{
    public bool Equals(Class_reglement x, Class_reglement y)
    {
        if (x.Numf == y.Numf)
        {
            return true;
        }
        else { return false; }
    }
    public int GetHashCode(Class_reglement codeh)
    {
        return 0;
    }
}


এই ব্লগটি কীভাবে আইক্যুয়ালিটি কম্পিউটারের পুরোপুরি ব্যবহার করতে হবে তা ব্যাখ্যা করে: blog.alex-turok.com/2013/03/c-linq-and-iequalitycomparer.html
জেরেমি রে ব্রাউন

উত্তর:


175

আপনার GetHashCodeবাস্তবায়ন সর্বদা একই মান প্রদান করে। Distinctদক্ষতার সাথে কাজ করার জন্য একটি ভাল হ্যাশ ফাংশনের উপর নির্ভর করে কারণ এটি অভ্যন্তরীণভাবে একটি হ্যাশ টেবিল তৈরি করে ।

ক্লাসগুলির ইন্টারফেসগুলি প্রয়োগ করার সময় ডকুমেন্টেশনটি পড়া গুরুত্বপূর্ণ , আপনি কোন চুক্তিটি কার্যকর করার কথা বলেছিলেন তা জানতে।

আপনার কোডে, সমাধানটি সেখানে প্রেরণ GetHashCodeকরা Class_reglement.Numf.GetHashCodeএবং এটি যথাযথভাবে প্রয়োগ করা।

তা ছাড়া, আপনার Equalsপদ্ধতিটি অপ্রয়োজনীয় কোডে পূর্ণ। এটি নিম্নলিখিত হিসাবে পুনরায় লেখা যেতে পারে (একই শব্দার্থক, কোডের ¼, আরও পাঠযোগ্য):

public bool Equals(Class_reglement x, Class_reglement y)
{
    return x.Numf == y.Numf;
}

শেষ অবধি, ToListকলটি অপ্রয়োজনীয় এবং সময়সাপেক্ষ: AddRangeএটির কোনও IEnumerableরূপান্তর Listপ্রয়োজন হয় না তাই গ্রহণ করে । AsEnumerableহয় এছাড়াও ফলাফলে প্রক্রিয়াকরণের যেহেতু এখানে অপ্রয়োজনীয় AddRangeএই যাহাই হউক না কেন কারণ হবে।


1 কোড কোড কোডটি আসলে কী করে তা না জেনে কার্গো কাল্ট প্রোগ্রামিং বলে । এটি একটি আশ্চর্যজনকভাবে ব্যাপক অনুশীলন। এটি মূলত কাজ করে না।


20
আপনার সমানগুলি ব্যর্থ হয় যখন x বা y নাল হয়।
ডিজেেন্ড্রাস

4
@dzendras একই জন্য GetHashCode। তবে নোট করুন যে ডকুমেন্টেশনটিIEqualityComparer<T>null আর্গুমেন্টগুলির সাথে কী করবেন তা নির্দিষ্ট করে না - তবে নিবন্ধে প্রদত্ত উদাহরণগুলিও হ্যান্ডেল করে nullনা।
কনরাড রুডল্ফ

50
কি দারুন. ঘৃণা অহেতুক কঠোর is আমরা একে অপরকে সাহায্য করার জন্য এসেছি, অপমান না করে। আমি অনুমান করি যে এটি কিছু লোককে হাসায়, তবে আমি এটি অপসারণের পরামর্শ দেব।
জেস

5
আমাকে উইকিতে "কার্গো কাল্ট প্রোগ্রামিং" সম্পর্কে পড়তে এবং তারপরে আমার স্কাইপ ট্যাগ লাইনটি "// ডিপ ম্যাজিক শুরু হয় ... এর পরে কিছু ভারী উইজার্ড্রি" শুরু করা হবে।
অ্যালেক্স

4
@ নীলবেন আপনি অভদ্রতার জন্য খোলামেলা পরামর্শ ভুল করেছেন। যেহেতু ওপি উত্তরটি গ্রহণ করেছে (এবং, আমি আরও কঠোর সংস্করণে লক্ষ্য করতে পারি!), তারা একই ভুল করেছে বলে মনে হয় না। আমি নিশ্চিত না যে আপনি কেন পরামর্শ দেন তা অভদ্র বলে মনে করেন, তবে আপনি যখন ভুল করে বলেন যে "লোকটির বক্তৃতা দরকার নেই"। আমি দৃ strongly়ভাবে একমত নই: বক্তৃতাটি দরকার ছিল এবং তা হৃদয়ঙ্গম করা হয়েছিল। লিখিত হিসাবে কোডটি খারাপ ছিল এবং খারাপ কাজের অনুশীলনের উপর ভিত্তি করে। এটি নির্দেশ না করা একটি বিপর্যয় হবে এবং কিছুটা সহায়ক হবে না, তখন থেকে ওপি তারা কীভাবে কাজ করে তা উন্নত করতে পারেনি।
কনরাড রুডলফ

47

এই কোডটি ব্যবহার করে দেখুন:

public class GenericCompare<T> : IEqualityComparer<T> where T : class
{
    private Func<T, object> _expr { get; set; }
    public GenericCompare(Func<T, object> expr)
    {
        this._expr = expr;
    }
    public bool Equals(T x, T y)
    {
        var first = _expr.Invoke(x);
        var sec = _expr.Invoke(y);
        if (first != null && first.Equals(sec))
            return true;
        else
            return false;
    }
    public int GetHashCode(T obj)
    {
        return obj.GetHashCode();
    }
}

এর ব্যবহারের উদাহরণ হবে

collection = collection
    .Except(ExistedDataEles, new GenericCompare<DataEle>(x=>x.Id))
    .ToList(); 

20
GetHashCodeএক্সপ্রেশনটিও ব্যবহার করা দরকার: এটি ব্যবহারের জন্য এই পোস্টটিreturn _expr.Invoke(obj).GetHashCode(); দেখুন ।
ওড়াদ

3

বাস্তবায়ন GetHashCodeএবং NULLবৈধতা সহ কেবল কোড :

public class Class_reglementComparer : IEqualityComparer<Class_reglement>
{
    public bool Equals(Class_reglement x, Class_reglement y)
    {
        if (x is null || y is null))
            return false;

        return x.Numf == y.Numf;
    }

    public int GetHashCode(Class_reglement product)
    {
        //Check whether the object is null 
        if (product is null) return 0;

        //Get hash code for the Numf field if it is not null. 
        int hashNumf = product.hashNumf == null ? 0 : product.hashNumf.GetHashCode();

        return hashNumf;
    }
}

উদাহরণ: Numf দ্বারা পৃথক Class_reglement তালিকা

List<Class_reglement> items = items.Distinct(new Class_reglementComparer());

2

আপনার তুলনা শ্রেণীর অন্তর্ভুক্তি (বা আরও নির্দিষ্টভাবে AsEnumerableআপনি যে কলটি এটির কাজ করার জন্য ব্যবহার করার প্রয়োজন হয়েছিল) তার মানে হল যে বাছাইয়ের যুক্তি ডাটাবেস সার্ভারের উপর ভিত্তি করে ডেটাবেস ক্লায়েন্টের (আপনার অ্যাপ্লিকেশন) হয়ে গেছে। এর অর্থ হ'ল আপনার ক্লায়েন্টকে এখন পুনরুদ্ধার করতে হবে এবং তারপরে একটি বৃহত সংখ্যক রেকর্ড প্রক্রিয়া করা দরকার, যা ডেটাবেজে যেখানে অ্যাপোপ্রেট সূচকগুলি ব্যবহার করা যেতে পারে সেখানে অনুসন্ধান সম্পাদন করা কম কার্যকর হবে।

পরিবর্তে আপনার প্রয়োজনীয়তাগুলি পূরণ করে এমন একটি ধারাটি বিকাশের চেষ্টা করা উচিত, আরও তথ্যের জন্য ক্লজ ব্যতীত সত্তাগুলির কাছে একটি লিনকিউ সহ একটি আইক্যুয়ালিটি কম্পারার ব্যবহার করে দেখুন।


2

আপনি যদি বক্সিং না করে জেনেরিক সমাধান চান:

public class KeyBasedEqualityComparer<T, TKey> : IEqualityComparer<T>
{
    private readonly Func<T, TKey> _keyGetter;

    public KeyBasedEqualityComparer(Func<T, TKey> keyGetter)
    {
        _keyGetter = keyGetter;
    }

    public bool Equals(T x, T y)
    {
        return EqualityComparer<TKey>.Default.Equals(_keyGetter(x), _keyGetter(y));
    }

    public int GetHashCode(T obj)
    {
        TKey key = _keyGetter(obj);

        return key == null ? 0 : key.GetHashCode();
    }
}

public static class KeyBasedEqualityComparer<T>
{
    public static KeyBasedEqualityComparer<T, TKey> Create<TKey>(Func<T, TKey> keyGetter)
    {
        return new KeyBasedEqualityComparer<T, TKey>(keyGetter);
    }
}

ব্যবহার:

KeyBasedEqualityComparer<Class_reglement>.Create(x => x.Numf)

0

IEquatable<T> আধুনিক ফ্রেমওয়ার্ক সহ এটি করার একটি আরও সহজ উপায় হতে পারে।

আপনি একটি দুর্দান্ত সরল bool Equals(T other)ফাংশন পেয়েছেন এবং ingালাই বা একটি পৃথক শ্রেণি তৈরির সাথে কোনও গোলযোগ নেই।

public class Person : IEquatable<Person>
{
    public Person(string name, string hometown)
    {
        this.Name = name;
        this.Hometown = hometown;
    }

    public string Name { get; set; }
    public string Hometown { get; set; }

    // can't get much simpler than this!
    public bool Equals(Person other)
    {
        return this.Name == other.Name && this.Hometown == other.Hometown;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();  // see other links for hashcode guidance 
    }
}

মনে রাখবেন যে GetHashCodeঅভিধানে বা এর মতো কিছু ব্যবহার করে এটি প্রয়োগ করতে হবে Distinct

পুনশ্চ. আমি মনে করি না যে কোনও কাস্টম সমতুল্য পদ্ধতিগুলি সরাসরি ডাটাবেস সাইডে সত্তা কাঠামোর সাথে কাজ করে (আমি মনে করি আপনি এটি জানেন কারণ আপনি AsEnumerable করেন) তবে সাধারণ ক্ষেত্রে সমান সমান করার জন্য এটি একটি খুব সহজ পদ্ধতি।

যদি জিনিসগুলি কাজ করছে বলে মনে হয় না (যেমন টোডোরিয়ালি করার সময় ডুপ্লিকেট কী ত্রুটিগুলি) এটির আঘাত হানা হচ্ছে কিনা তা নিশ্চিত করার জন্য এবং আপনার GetHashCodeসংজ্ঞায়িত (ওভাররাইড কীওয়ার্ড সহ) নিশ্চিত করার জন্য ইক্যুয়ালগুলির মধ্যে একটি ব্রেকপয়েন্ট স্থাপন করে ।


4
আপনাকে এখনও নাল
ডিস্ক্লোজার

আমি কখনই এর মধ্যে দৌড়ে যাইনি তবে আমি পরের বার মনে করব। আপনার কি কোনও তালিকার শূন্যতা আছে <T> বা এর মতো কিছু?
সাইমন_ ওয়েভার 24'18

4
যে .Equals()পদ্ধতির অধীনে other.Hometownআপনি নিজেকে তার সাথে তুলনা করেছেন বলে মনে হচ্ছেthis.Hometown
জেক স্টোকস

উফ! ফিক্সড টাইপো :)
সাইমন_উইভার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.