Thursday, November 9, 2017

C# For Beginners , Part -43 ( Overriding Equals() Method )

আজকে  আমরা  Equals() মেথোড  নিয়ে  কথা  বলবো  ।।  ধরো , আমরা দুইটা সংখ্যার চেক করে দেখবো সমান কি না  ??  যদি  সমান  হয়  ,  তাহলে  আউটপুট-এ  True আর না হলে  আউটপুট-এ  False | এই বিষয়টিই , আমরা এনাম দিয়ে করে আসি , তাহলে ওটাও প্র্যাকটিস হয়ে গেলো একটু ------------

using System;

using System.Collections.Generic;

namespace joy
{
    public class Program
    {
        public static void Main()
        {
            Direction d1 = Direction.East;
            Direction d2 = Direction.West;

            Console.WriteLine(d1 == d2);
            Console.WriteLine(d1.Equals(d2));
           
            Console.ReadKey();
        }
    }
    public enum Direction

    {

        East=1,
        West=2
      
    }
}

আচ্ছা আমরা একটা এনাম ক্রিয়েট করেছি , যার ইলিমেন্ট দুইটা ।। তারপর , তাদের মান চেক করেছি , যদি সমান হয় তাহলে  True আর না হলে  False দেখাবে ।। এখানে আমরা আউটপুটের জনয দুইটা পদ্ধতি ইউজ করেছি , একটা  d1 == d2 , আরেকটা   d1.Equals(d2) ।।  তো দুইটাতেই আমাদের একই আউটপুট দেখাচ্ছে , খুবই ভালো কথা - কিন্তু আমরা এই দুইটার মধ্যে পার্থক্য বুঝতে পারছি না ।। তো চলো , আরেকটু এগিয়ে যাই , তাহলে আসতে  আসতে  সব বুঝতে পারবো ।। নতুন আরেকটা কোড দেখি ------------------

using System;

using System.Collections.Generic;

namespace joy
{
    public class Program
    {
        public static void Main()
        {
            Customer C1 = new Customer();
            C1.FirstName = "Nayeem";
            C1.LastName = "Shahriar";
            Customer C2 = C1;
            Console.WriteLine(C2==C1);
            Console.WriteLine(C2.Equals(C1));
           
            Console.ReadKey();
        }
    }
    public class Customer
    {
        public string FirstName { set; get; }
        public string LastName { set; get; }
      
    }
}

এখানে আমরা কি করলাম ?? একটা ক্লাসই ক্রিয়েট করে ফেললাম  । ।   তারপর মেইন মেথোড-এ একই ক্লাসের দুইটি রেফারেন্স ভ্যারিয়েবল   (   C1 ও  C2 ) ক্রিয়েট করলাম , কিন্তু আমাদের কিন্তু এটা মাথায় রাখতে হবে এই দুইটা রেফারেন্স ভ্যারিয়েবলই কিন্তু একটা অব্জেক্টকে পয়েন্ট করছে ।। তাই , আমি যখন রেফারেন্স টাইপ গুলোকে কম্পেয়ার করাই তখন যেহেতু দুইটা রেফারেন্স ভ্যারিয়েবল একই অব্জেক্টকে পয়েন্ট করছে , তাই তাদের সমান ধরে নেয়া হয় , আর তাই আউটপুট  True  আসবে , আর দুইটারই একই অব্জেক্ট পয়েন্ট করা থাকলে , অবশ্যই তাদের মানও সমান হবে ।।

আচ্ছা , এবার আমরা একই ক্লাসের দুইটা রেফারেন্স ভ্যারিয়েবল ক্রিয়েট করবো , সাথে দুইটা অবজেক্টও  ।। চলো দেখি কি হয় ????????????????

using System;

using System.Collections.Generic;

namespace joy
{
    public class Program
    {
        public static void Main()
        {
            Customer C1 = new Customer();
            C1.FirstName = "Nayeem";
            C1.LastName = "Shahriar";
            Customer C2 = new Customer();
            C2.FirstName = "Nayeem";
            C2.LastName = "Shahriar";
            Console.WriteLine(C2==C1);
            Console.WriteLine(C2.Equals(C1));
           
            Console.ReadKey();
        }
    }
    public class Customer
    {
        public string FirstName { set; get; }
        public string LastName { set; get; }
      
    }
}

কোডটি রান করে দেখো , কি আউটপুট আসে ??

এবার কি হলো ?? বলো তো দেখি ?? হুম আমাদের দুই ক্ষেত্রেই একই নাম ব্যবহার করেছি , তারপরো আমাদের এক দেখালো না !! এর কারণ , নিশ্চই বুঝতে পেরেছো ইতিমধ্যে ।। আমরা দুই দুইটা আলাদা আলাদা অব্জেক্ট ক্রিয়েট করেছি সাথে সাথে দুই দুইটা আলাদা আলাদা রেফারেন্স ভ্যারিয়েবল  । যখন আমরা , আলাদা আলাদা ভ্যারিয়েবল চেক করাতে গেলাম , তখনই প্রথম ধাক্কাতে হেরে গেলাম , কারণ দুইটা ভ্যারিয়েবলই আলাদা আলাদা অব্জেক্টকে পয়েন্ট করছে ।।  তাই সেখান থেকেই , ধরে নেয়া হয়েছে যে তারা সমান নয় , এই কারণে - আউটপুটে False পেয়েছি ।।

এখন এই সমস্যা থেকে বাচতে , আমাদের সাহায্য করবে আমাদের  Equals() মেথোড ।। তার ডিফল্টভাবে যে ভারচুয়াল মেথোড আছে , তার   উপরে আমরা ওভাররাইড করার সুযোগ আছে ,আমরা এখন এই সুযোগ ব্যবহার করবো ।।

using System;

using System.Collections.Generic;

namespace joy
{
    public class Program
    {
        public static void Main()
        {
            Customer C1 = new Customer();
            C1.FirstName = "Nayeem";
            C1.LastName = "Shahriar";
            Customer C2 = new Customer();
            C2.FirstName = "Nayeem";
            C2.LastName = "Shahriar";
            Console.WriteLine(C2==C1);
            Console.WriteLine(C2.Equals(C1));
           
            Console.ReadKey();
        }
    }
    public class Customer
    {
        public string FirstName { set; get; }
        public string LastName { set; get; }

        public override bool Equals(object obj)
        {
            if(obj==null)
            {
                return false;
            }
            if(!(obj is Customer))
            {
                return false;
            }

            return this.FirstName == ((Customer)obj).FirstName && this.LastName == ((Customer)obj).LastName;
        }
        public override int GetHashCode()
        {
            return this.FirstName.GetHashCode() ^ this.LastName.GetHashCode();
        }
      
    }
}

তো , আমরা ঠিকঠাকভাবেই সেই সুযোগ ব্যবহার করেছি ।। যদি , আমরা Equals মেথোদের মধ্যে  object টাইপে যে পযারামিটার পাঠাবো , সেটা যদি নাল হয় , তাহলে রিটার্ন তো ভুল হবেই । আর , যদি আমাদের প্যারামিটার হয় অন্য কোনো ক্লাসের টাইপের !! তাহলে তো , কখনো ভিন্ন কোনো টাইপের জিনিস কম্পেয়ার করা হয় না , তাই ভুল হবে ।    [ !(obj is Customer) ]

আর তারপর নামগুলো সমান কি না ?? সেটা চেক করে , তারপর রিটারন করবো [ return this.FirstName == ((Customer)obj).FirstName && this.LastName == ((Customer)obj).LastName;]

আর আমাদের ওয়ারনিং এড়ানোর জন্য , আমরা যখন  Equals  মেথোডের ওভাররাইড করবো , তখন -  GetHashCode() মেথোডেরও ওভাররাইড করবো , এই মেথোড এক ধরনের হ্যাশকোড প্রদান করে যা , সাধারণত এক ধরণের নিউমেরিক ভ্যালু যেটা একটা অব্জেক্ট এর আইডেনটিফেকিশেন হিসেবে কাজ করে , এর সাহায্যে আমরা - দুইটি অব্জেক্ট এর ইকুয়ালিটি চেক করতে পারি খুব এফিশিয়েন্ট ভাবে ।। দুইটা অব্জেক্ট  সমান হলে তাদের হ্যাশকোডও সমান হয় , বাট দুইটা হ্যাশকোড সমান হলেই যে সেই অব্জেক্ট দুটো সমান হবে , তা কিন্তু নয় !! দুইটা অসমান অব্জেক্ট এরও হ্যাশকোড সমান হতে পারে !!!

আসলে , আমরা যখন এই ইকুয়াল মেথোড কল করে , দুইটা অব্জেক্ট এর ইকুয়ালিটি চেক করি তখন অটোমেটিকভাবেই .GetHashCode মেথোড কল করে , হ্যাশ কোড বের করে চেক করে , তাই আমরা
ইকুয়াল মেথোড ইউজ করলে , সাথে সাথে  GetHashCode() মেথোডও অভাররাইড করে দেবো , যদিও আপাতভাবে আমাদের কাছে , এই মেথোড এর কোনো কাজ নেই ।।

 এই বিষয়ে পরবরতিতে বিস্তারিত কথা বলবো ,

আজ কে  আর নয় -----------------------

No comments:

Post a Comment