যেহেতু আমি এমন কোনও উত্তর খুঁজে পাইনি যা ব্যাখ্যা করে যে আমাদের কেন ওভাররাইড করা উচিত GetHashCode
এবং Equals
কাস্টম স্ট্রাক্টগুলির জন্য এবং কেন ডিফল্ট রূপায়ণ "হ্যাশ টেবিলের কী হিসাবে ব্যবহারের পক্ষে উপযুক্ত নয়", তাই আমি এই ব্লগে একটি লিঙ্ক রেখে যাব পোস্ট , যা ব্যাখ্যা করে যে কেন ঘটেছে সমস্যার বাস্তব ক্ষেত্রে উদাহরণ সহ।
আমি পুরো পোস্টটি পড়ার পরামর্শ দিচ্ছি, তবে এখানে একটি সংক্ষিপ্ত বিবরণ দেওয়া হয়েছে (জোর দেওয়া এবং ব্যাখ্যাগুলি যোগ করা হয়েছে)
স্ট্রাইকগুলির জন্য ডিফল্ট হ্যাশ কারণ ধীর এবং খুব ভাল নয়:
সিএলআরটি যেভাবে ডিজাইন করা হয়েছে, প্রতিটি সদস্যের কাছে সংজ্ঞায়িত System.ValueType
বা কলগুলিতে কল করা System.Enum
[ বক্সিং ] বক্সিং বক্সিং বরাদ্দের কারণ হতে পারে [...]
হ্যাশ ফাংশনের একজন প্রয়োগকারী একটি দ্বিধাদ্বন্দ্বের মুখোমুখি হন: হ্যাশ ফাংশনটির একটি ভাল বিতরণ করুন বা এটি দ্রুত তৈরি করুন। কিছু কিছু ক্ষেত্রে, এটা তাদের উভয় অর্জন করা সম্ভব, কিন্তু এটা জেনেরিক এই কাজ করতে হার্ড মধ্যে ValueType.GetHashCode
।
স্ট্রাক্টের ক্যানোনিকাল হ্যাশ ফাংশন সমস্ত ক্ষেত্রের "সংযুক্ত" হ্যাশ কোডগুলি। তবে কোনও ValueType
পদ্ধতিতে ক্ষেত্রের একটি হ্যাশ কোড পাওয়ার একমাত্র উপায় হ'ল প্রতিচ্ছবি ব্যবহার করা । সুতরাং, সিএলআর লেখকগণ বিতরণে গতি নিয়ে বাণিজ্য করার সিদ্ধান্ত নিয়েছে এবং ডিফল্ট GetHashCode
সংস্করণটি কেবল প্রথম নন-ফিল্ডের একটি হ্যাশ কোড দেয় এবং এটি টাইপ আইডি দিয়ে "মুঙ্গ করে" [...] এটি যুক্তিসঙ্গত আচরণ হয় যদি না এটি হয় । উদাহরণস্বরূপ, যদি আপনি যথেষ্ট দুর্ভাগ্য হন এবং আপনার কাঠামোর প্রথম ক্ষেত্রটির বেশিরভাগ ক্ষেত্রে একই মান থাকে তবে একটি হ্যাশ ফাংশন সর্বদা একই ফলাফল সরবরাহ করবে । এবং, আপনি যেমন কল্পনা করতে পারেন, যদি এই দৃষ্টান্তগুলি হ্যাশ সেট বা হ্যাশ টেবিলের মধ্যে সংরক্ষণ করা হয় তবে এটি কঠোর পারফরম্যান্সের প্রভাব ফেলবে।
[...] প্রতিবিম্ব-ভিত্তিক বাস্তবায়ন ধীর । খুব ধীর.
[...] উভয় ValueType.Equals
এবং ValueType.GetHashCode
একটি বিশেষ অপ্টিমাইজেশন রয়েছে। যদি কোনও ধরণের "পয়েন্টার" না থাকে এবং সঠিকভাবে প্যাক করা থাকে [...] তবে আরও সর্বোত্তম সংস্করণ ব্যবহৃত হয়: GetHashCode
একটি উদাহরণের সাথে পুনরাবৃত্তি হয় এবং 4 বাইট এবং Equals
পদ্ধতির XORs ব্লক ব্যবহার করে দুটি দৃষ্টান্তের তুলনা করে memcmp
। [...] তবে অপ্টিমাইজেশনটি খুব জটিল। প্রথমত, অপ্টিমাইজেশন সক্ষম করা কবে হবে তা জানা শক্ত [...] দ্বিতীয়ত, একটি মেমরি তুলনা অগত্যা আপনাকে সঠিক ফলাফল দেয় না । এখানে একটি সহজ উদাহরণ: [...] -0.0
এবং +0.0
সমান তবে বিভিন্ন বাইনারি উপস্থাপনা রয়েছে।
পোস্টে বর্ণিত রিয়েল-ওয়ার্ল্ড ইস্যু:
private readonly HashSet<(ErrorLocation, int)> _locationsWithHitCount;
readonly struct ErrorLocation
{
// Empty almost all the time
public string OptionalDescription { get; }
public string Path { get; }
public int Position { get; }
}
আমরা একটি টিউপল ব্যবহার করেছি যাতে ডিফল্ট সমতা প্রয়োগের সাথে একটি কাস্টম স্ট্রাক্ট থাকে। এবং দুর্ভাগ্যক্রমে, কাঠামোর একটি alচ্ছিক প্রথম ক্ষেত্র ছিল যা প্রায় সর্বদা [খালি স্ট্রিং] এর সমান । কয়েক হাজার আইটেম দিয়ে সংগ্রহ শুরু করার জন্য কয়েক মিনিট সময় নিলে সেটটিতে উপাদানগুলির সংখ্যা উল্লেখযোগ্যভাবে বৃদ্ধি পেয়ে একটি বাস্তব পারফরম্যান্স সমস্যার কারণ হয় until
সুতরাং, "আমার নিজের ক্ষেত্রে কী কী প্যাক করা উচিত এবং কোন ক্ষেত্রে আমি নিরাপদে ডিফল্ট বাস্তবায়নের উপর নির্ভর করতে পারি" এই প্রশ্নের উত্তর দেওয়ার জন্য, কমপক্ষে স্ট্রাক্টের ক্ষেত্রে আপনাকে ওভাররাইড করা উচিত Equals
এবং GetHashCode
যখনই আপনার কাস্টম স্ট্রাক্ট হিসাবে ব্যবহার করা যেতে পারে একটি হ্যাশ টেবিল বা Dictionary
। বক্সিং এড়ানোর জন্য
আমি IEquatable<T>
এই ক্ষেত্রে প্রয়োগেরও সুপারিশ করব ।
হিসাবে অন্যান্য উত্তর বলেন, যদি আপনি একটি লেখার বর্গ , ডিফল্ট রেফারেন্স সমতা ব্যবহার হ্যাশ সাধারণত জরিমানা, তাই আমি এই ক্ষেত্রে বিরক্ত করেনি, হয় যদি না আপনি ওভাররাইড প্রয়োজন Equals
(তারপর আপনি ওভাররাইড করতে হবে GetHashCode
সেই অনুযায়ী)।