সি # .একুয়ালস (),। রেফারেন্সইকুয়ালস () এবং == অপারেটর


85

এই তিনটি সম্পর্কে আমার বোঝাপড়াটি ছিল:

  • .Equals()ডেটা সমতা জন্য পরীক্ষা (আরও ভাল বর্ণনার অভাবের জন্য)। .Equals()একই বস্তুর বিভিন্ন উদাহরণের জন্য সত্য ফিরে আসতে পারে এবং এটি সর্বাধিক সাধারণ ওভাররাইড পদ্ধতি।

  • .ReferenceEquals() দুটি বস্তু একই উদাহরণ এবং ওভাররাইড করা যায় না তা পরীক্ষা করে।

  • ==ReferenceEquals()ডিফল্ট হিসাবে একই , কিন্তু এই ওভাররাইড করা যেতে পারে।

তবে সি # স্টেশনটি বলে:

অবজেক্ট শ্রেণিতে, Equalsএবং ReferenceEqualsপদ্ধতিগুলি শব্দার্থগতভাবে সমতুল্য, ব্যতীত ReferenceEqualsকেবলমাত্র বস্তুর উদাহরণগুলিতে কাজ করে। ReferenceEqualsপদ্ধতি স্ট্যাটিক হয়।

এখন আমি তা পাই না। কেউ কি এটার উপর একটু আলো ফেলতে পারো?



দেখুন stackoverflow.com/questions/814878/... এই বিষয়ে এবং অন্যান্য অনেক Stackoverflow প্রশ্ন।
ইয়ান মেরার

আমার কাছে এটি কেবলমাত্র আমি সি # স্টেশন থেকে উত্তেজিত অংশ যা আমাকে বিভ্রান্ত করছে।
999999

উত্তর:


87

আপনার বিভ্রান্তির উত্সটি দেখে মনে হচ্ছে যে সি # স্টেশন থেকে নিষ্কাশনে একটি টাইপো রয়েছে, যা পড়তে হবে: "... ইকুয়ালগুলি কেবলমাত্র বস্তুর উদাহরণগুলিতে কাজ করে except রেফারেন্সএকোয়ালস পদ্ধতি অচল।"


প্রত্যেকটির শব্দার্থক অর্থগুলির পার্থক্য সম্পর্কে আপনি আলগাভাবে সঠিক (যদিও "একই বস্তুর বিভিন্ন উদাহরণ" কিছুটা বিভ্রান্ত বলে মনে হচ্ছে, এটি সম্ভবত "একই ধরণের বিভিন্ন উদাহরণ ) পড়তে হবে এবং যার সম্পর্কে ওভাররাইড করা যেতে পারে।

যদি আমরা এটিকে একপাশে ছেড়ে দিই, আসুন আপনার প্রশ্নের শেষ বিটটি মোকাবেলা করুন, যেমন তারা কীভাবে সরল System.Objectদৃষ্টান্ত এবং System.Objectরেফারেন্সগুলি দিয়ে কাজ করে (আমাদের উভয়েরই অ-বহুরূপী প্রকৃতিটি ডজ করার প্রয়োজন হয় ==)। এখানে, তিনটি অপারেশন সমানভাবে কাজ করবে তবে একটি সতর্কতার সাথে: চালিত Equalsহওয়া যায় না null

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

ReferenceEqualsএকটি স্থিতিশীল পদ্ধতি যা দুটি / দুটি পরামিতি গ্রহণ করে null। যেহেতু এটি স্থিতিশীল (কোনও অবজেক্টের উদাহরণের সাথে সম্পর্কিত নয় ), এটি NullReferenceExceptionকোনও অবস্থাতেই ফেলে দেবে না ।

==একটি অপারেটর, যে, এই ক্ষেত্রে ( object), একইরকম আচরণ করে ReferenceEquals। এটি একটিও ফেলে দেবে না NullReferenceException

বর্ণনা করা:

object o1 = null;
object o2 = new object();

//Technically, these should read object.ReferenceEquals for clarity, but this is redundant.
ReferenceEquals(o1, o1); //true
ReferenceEquals(o1, o2); //false
ReferenceEquals(o2, o1); //false
ReferenceEquals(o2, o2); //true

o1.Equals(o1); //NullReferenceException
o1.Equals(o2); //NullReferenceException
o2.Equals(o1); //false
o2.Equals(o2); //true

তাহলে কি সি # স্টেশন থেকে উদ্ধৃত অংশগুলি উপরে ভুল উদ্ধৃত হয়েছে (বিশেষত যদি আমি ওভাররাইড করি .Equals())?
999999

4
উদ্ধৃতাংশ যুক্তরাষ্ট্রের "এ objectশ্রেণী" । আমার মনে হয় আপনি সেই অংশটি বাদ দিয়েছেন? কারণ অন্যথায় আপনি এটিকে ওভাররাইড করার কথা বলবেন না।
ডোমেনিক

4
আমার উত্তরটি কেবলobject ক্লাস সম্পর্কে ।
অনি

@ অ্যানি: আপনার নীচের বাক্যটি ছিল ভুল স্থিতিশীল পদ্ধতি নুলারফেরান এক্সেক্সশনটি ফেলে দিতে পারে: যেহেতু এটি স্থির (কোনও বস্তুর উদাহরণের সাথে সম্পর্কিত নয়), এটি কোনও পরিস্থিতিতেই নালরফেরান এক্সেকশন নিক্ষেপ করবে না।
সেলভরাজ

4
Equals এছাড়াও একটি স্থিতিশীল পদ্ধতি object যাতে দুটি পরামিতি লাগে। এক বা উভয় হতে পারে null
ওয়েস্টন

20

বিষয়টির এই এমএসডিএন নিবন্ধটি দেখুন ।

আমি মনে করি প্রাসঙ্গিক বিষয়গুলি:

রেফারেন্সের সমতার জন্য পরীক্ষা করতে, রেফারেন্সক্যুয়ালগুলি ব্যবহার করুন। মান সমতা পরীক্ষা করার জন্য, সমান বা সমান ব্যবহার করুন।

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

আশাকরি এটা সাহায্য করবে!


6
দুর্ভাগ্যক্রমে, লিঙ্কটি মারা গেছে। প্রাসঙ্গিক তথ্য অনুলিপি করার জন্য +1।
প্যাক 0

7

.ReferencesEquals সম্পর্কে আপনার বোঝাটি সঠিক।

.মানগুলি মূল্য প্রকারের জন্য ডেটা সমতা এবং অ-মান ধরণের জন্য (সাধারণ বস্তু) রেফারেন্স সমতা পরীক্ষা করে।

.অন্যত্বের সমতা পরীক্ষার কোনও ফর্ম সম্পাদন করার জন্য অবজেক্টগুলির জন্য সমাপ্তিগুলি ওভাররাইড করা যায়

সম্পাদনা: এছাড়াও,। রেফারেন্সইক্যুয়ালগুলি মান ধরণের ক্ষেত্রে ব্যবহার করা যায় না (এটি ভাল তবে এটি সর্বদা মিথ্যা হবে)


3

"নাল" এর সাথে তুলনা করার বিষয়ে আমার পাঁচটি সেন্ট যুক্ত করতে চান।

  1. রেফারেন্সএকুয়ালস (অবজেক্ট, অবজেক্ট) "" (অবজেক্ট) আরগ 1 == আরগ 2 "এর সমান (তাই মানের ধরণের ক্ষেত্রে, আপনি বক্সিং পান এবং এটি সময় নেয়)। তবে এই পদ্ধতিটি বিভিন্ন পরিস্থিতিতে যেমন নালীর জন্য আপনার যুক্তি পরীক্ষা করার একমাত্র 100% নিরাপদ উপায়

    • ক) এর মাধ্যমে সদস্যদের কল করার আগে। অপারেটর
    • খ) এএস অপারেটরের ফলাফল পরীক্ষা করা।
  2. == এবং সমান ()। আমি কেন বলছি যে নাল-চেকিংয়ের সাথে রেফারেন্সকুয়ালগুলি 100% নিরাপদ? কল্পনা করুন যে আপনি জেনেরিক এক্সটেনশনগুলি মূল ক্রস-প্রজেক্ট লাইবগুলিতে লিখেছেন এবং আপনাকে জেনেরিক প্যারামিটার প্রকারটি কিছু ডোমেন প্রকারের মধ্যে সীমাবদ্ধ রাখতে বলুন। এই ধরণের "==" অপারেটর - এখন বা পরে পরিচয় করিয়ে দিতে পারে (এবং বিশ্বাস করুন, আমি অনেক কিছু দেখেছি, এই অপারেটরটির খুব "অদ্ভুত" যুক্তি থাকতে পারে, বিশেষত যদি এটি ডোমেন বা জেদী অবজেক্টের ক্ষেত্রে আসে)। আপনি আপনার নালীর পক্ষে যুক্তি যাচাই করার চেষ্টা করুন এবং তারপরে এতে সদস্য অপারেশনটি কল করুন। অবাক, আপনার এখানে নুলারফ থাকতে পারে। কারণ == অপারেটর প্রায় সমান () সমান এবং খুব কাস্টম এবং খুব অবিশ্বাস্য। তবুও একটি পার্থক্য রয়েছে, যা বিবেচনায় নেওয়া উচিত - আপনি যদি নিজের জেনেরিক প্যারামিটারটিকে কিছু কাস্টম প্রকারের মধ্যে সীমাবদ্ধ না করেন (== কেবলমাত্র আপনার ধরণটি "শ্রেণি" হলে ব্যবহার করা যেতে পারে), == অপারেটর অবজেক্টের মতোই । রেফারেন্সএকুয়ালস (..)। ভার্চুয়াল হিসাবে সমান বাস্তবায়ন সর্বদা চূড়ান্ত প্রকার থেকে ব্যবহৃত হয়।

সুতরাং আমার সুপারিশটি হ'ল, আপনি যখন নিজের ধরণের লেখেন বা সুপরিচিত প্রকারগুলি থেকে প্রাপ্ত হন, আপনি নাল পরীক্ষা করার জন্য == ব্যবহার করতে পারেন। অন্যথায় অবজেক্টটি ব্যবহার করুন e রেফারেন্সইকুয়ালস (আরগ, নাল)।


1

অবজেক্ট শ্রেণিতে। সমানতা সমতা নয়, পরিচয় প্রয়োগ করে। রেফারেন্স সমান কিনা তা এটি পরীক্ষা করে। কোডটি এর মতো হতে পারে:

public virtual Boolean Equals(Object other) {
    if (this == other) return true;
    return false;
}

বাস্তবায়ন করার সময়। আপনার ক্লাসে সমান পরিমাণগুলি আপনাকে বেস ক্লাসে কল করা উচিত। বেস ক্লাসটি অবজেক্ট না হলে কেবলমাত্র সমাপ্তি। হ্যাঁ, এটা জটিল।

আরও বেশি হিসাবে, উত্পন্ন ক্লাসগুলি ওভাররাইড করতে পারে quএকটি কোয়েলস এবং তাই আপনি এটি সনাক্ত করতে মাইক্রোসফ্ট স্ট্যাটিক যুক্ত পরীক্ষা করতে পারেন না e রেফারেন্সএকোয়ালস পদ্ধতি।

আপনি যদি কিছু ক্লাস ব্যবহার করেন তবে আপনার জন্য যৌক্তিকভাবে


1

রেফারেন্সের ধরণগুলি এবং ওভাররাইড সমতা পদ্ধতিগুলি নিয়ে কাজ করার সময় মূল পার্থক্যগুলি দেখানোর জন্য আমি অ্যানির দুর্দান্ত উত্তরে প্রসারিত করেছি ।

  • আপনি এই কোডটির কার্যকারী সংস্করণটি এখানে দেখতে পাবেন: https://dotnetfiddle.net/dFKMhB
  • বিকল্পভাবে, এই কোডটি লিনকপ্যাডে আটকানো হবে এবং এটি হিসাবে চালানো হবে Language: C# Program

void Main()
{

    //odd os are null; evens are not null
    object o1 = null;
    object o2 = new object();
    object o3 = null;
    object o4 = new object();
    object o5 = o1;
    object o6 = o2;

    Demo d1 = new Demo(Guid.Empty);
    Demo d2 = new Demo(Guid.NewGuid());
    Demo d3 = new Demo(Guid.Empty);

    Debug.WriteLine("comparing null with null always yields true...");
    ShowResult("ReferenceEquals(o1, o1)", () => ReferenceEquals(o1, o1)); //true
    ShowResult("ReferenceEquals(o3, o1)", () => ReferenceEquals(o3, o1)); //true
    ShowResult("ReferenceEquals(o5, o1)", () => ReferenceEquals(o5, o1)); //true 
    ShowResult("o1 == o1", () => o1 == o1); //true
    ShowResult("o3 == o1", () => o3 == o1); //true
    ShowResult("o5 == o1", () => o5 == o1); //true 

    Debug.WriteLine("...though because the object's null, we can't call methods on the object (i.e. we'd get a null reference exception).");
    ShowResult("o1.Equals(o1)", () => o1.Equals(o1)); //NullReferenceException
    ShowResult("o1.Equals(o2)", () => o1.Equals(o2)); //NullReferenceException
    ShowResult("o3.Equals(o1)", () => o3.Equals(o1)); //NullReferenceException
    ShowResult("o3.Equals(o2)", () => o3.Equals(o2)); //NullReferenceException
    ShowResult("o5.Equals(o1)", () => o5.Equals(o1));  //NullReferenceException
    ShowResult("o5.Equals(o2)", () => o5.Equals(o1));  //NullReferenceException

    Debug.WriteLine("Comparing a null object with a non null object always yeilds false");
    ShowResult("ReferenceEquals(o1, o2)", () => ReferenceEquals(o1, o2)); //false
    ShowResult("ReferenceEquals(o2, o1)", () => ReferenceEquals(o2, o1)); //false
    ShowResult("ReferenceEquals(o3, o2)", () => ReferenceEquals(o3, o2)); //false
    ShowResult("ReferenceEquals(o4, o1)", () => ReferenceEquals(o4, o1)); //false
    ShowResult("ReferenceEquals(o5, o2)", () => ReferenceEquals(o3, o2)); //false
    ShowResult("ReferenceEquals(o6, o1)", () => ReferenceEquals(o4, o1)); //false
    ShowResult("o1 == o2)", () => o1 == o2); //false
    ShowResult("o2 == o1)", () => o2 == o1); //false
    ShowResult("o3 == o2)", () => o3 == o2); //false
    ShowResult("o4 == o1)", () => o4 == o1); //false
    ShowResult("o5 == o2)", () => o3 == o2); //false
    ShowResult("o6 == o1)", () => o4 == o1); //false
    ShowResult("o2.Equals(o1)", () => o2.Equals(o1)); //false
    ShowResult("o4.Equals(o1)", () => o4.Equals(o1)); //false
    ShowResult("o6.Equals(o1)", () => o4.Equals(o1)); //false

    Debug.WriteLine("(though again, we can't call methods on a null object:");
    ShowResult("o1.Equals(o2)", () => o1.Equals(o2)); //NullReferenceException
    ShowResult("o1.Equals(o4)", () => o1.Equals(o4)); //NullReferenceException
    ShowResult("o1.Equals(o6)", () => o1.Equals(o6)); //NullReferenceException

    Debug.WriteLine("Comparing 2 references to the same object always yields true");
    ShowResult("ReferenceEquals(o2, o2)", () => ReferenceEquals(o2, o2)); //true    
    ShowResult("ReferenceEquals(o6, o2)", () => ReferenceEquals(o6, o2)); //true <-- Interesting
    ShowResult("o2 == o2", () => o2 == o2); //true  
    ShowResult("o6 == o2", () => o6 == o2); //true <-- Interesting
    ShowResult("o2.Equals(o2)", () => o2.Equals(o2)); //true 
    ShowResult("o6.Equals(o2)", () => o6.Equals(o2)); //true <-- Interesting

    Debug.WriteLine("However, comparing 2 objects may yield false even if those objects have the same values, if those objects reside in different address spaces (i.e. they're references to different objects, even if the values are similar)");
    Debug.WriteLine("NB: This is an important difference between Reference Types and Value Types.");
    ShowResult("ReferenceEquals(o4, o2)", () => ReferenceEquals(o4, o2)); //false <-- Interesting
    ShowResult("o4 == o2", () => o4 == o2); //false <-- Interesting
    ShowResult("o4.Equals(o2)", () => o4.Equals(o2)); //false <-- Interesting

    Debug.WriteLine("We can override the object's equality operator though, in which case we define what's considered equal");
    Debug.WriteLine("e.g. these objects have different ids, so we treat as not equal");
    ShowResult("ReferenceEquals(d1,d2)",()=>ReferenceEquals(d1,d2)); //false
    ShowResult("ReferenceEquals(d2,d1)",()=>ReferenceEquals(d2,d1)); //false
    ShowResult("d1 == d2",()=>d1 == d2); //false
    ShowResult("d2 == d1",()=>d2 == d1); //false
    ShowResult("d1.Equals(d2)",()=>d1.Equals(d2)); //false
    ShowResult("d2.Equals(d1)",()=>d2.Equals(d1)); //false
    Debug.WriteLine("...whilst these are different objects with the same id; so we treat as equal when using the overridden Equals method...");
    ShowResult("d1.Equals(d3)",()=>d1.Equals(d3)); //true <-- Interesting (sort of; different to what we saw in comparing o2 with o6; but is just running the code we wrote as we'd expect)
    ShowResult("d3.Equals(d1)",()=>d3.Equals(d1)); //true <-- Interesting (sort of; different to what we saw in comparing o2 with o6; but is just running the code we wrote as we'd expect)
    Debug.WriteLine("...but as different when using the other equality tests.");
    ShowResult("ReferenceEquals(d1,d3)",()=>ReferenceEquals(d1,d3)); //false <-- Interesting (sort of; same result we had comparing o2 with o6; but shows that ReferenceEquals does not use the overridden Equals method)
    ShowResult("ReferenceEquals(d3,d1)",()=>ReferenceEquals(d3,d1)); //false <-- Interesting (sort of; same result we had comparing o2 with o6; but shows that ReferenceEquals does not use the overridden Equals method)
    ShowResult("d1 == d3",()=>d1 == d3); //false <-- Interesting (sort of; same result we had comparing o2 with o6; but shows that ReferenceEquals does not use the overridden Equals method)
    ShowResult("d3 == d1",()=>d3 == d1); //false <-- Interesting (sort of; same result we had comparing o2 with o6; but shows that ReferenceEquals does not use the overridden Equals method)


    Debug.WriteLine("For completeness, here's an example of overriding the == operator (wihtout overriding the Equals method; though in reality if overriding == you'd probably want to override Equals too).");
    Demo2 d2a = new Demo2(Guid.Empty);
    Demo2 d2b = new Demo2(Guid.NewGuid());
    Demo2 d2c = new Demo2(Guid.Empty);
    ShowResult("d2a == d2a", () => d2a == d2a); //true
    ShowResult("d2b == d2a", () => d2b == d2a); //false
    ShowResult("d2c == d2a", () => d2c == d2a); //true <-- interesting
    ShowResult("d2a != d2a", () => d2a != d2a); //false
    ShowResult("d2b != d2a", () => d2b != d2a); //true
    ShowResult("d2c != d2a", () => d2c != d2a); //false <-- interesting
    ShowResult("ReferenceEquals(d2a,d2a)", () => ReferenceEquals(d2a, d2a)); //true
    ShowResult("ReferenceEquals(d2b,d2a)", () => ReferenceEquals(d2b, d2a)); //false
    ShowResult("ReferenceEquals(d2c,d2a)", () => ReferenceEquals(d2c, d2a)); //false <-- interesting
    ShowResult("d2a.Equals(d2a)", () => d2a.Equals(d2a)); //true
    ShowResult("d2b.Equals(d2a)", () => d2b.Equals(d2a)); //false
    ShowResult("d2c.Equals(d2a)", () => d2c.Equals(d2a)); //false <-- interesting   

}



//this code's just used to help show the output in a friendly manner
public delegate bool Statement();
void ShowResult(string statementText, Statement statement)
{
    try 
    {
        Debug.WriteLine("\t{0} => {1}",statementText, statement());
    }
    catch(Exception e)
    {
        Debug.WriteLine("\t{0} => throws {1}",statementText, e.GetType());
    }
}

class Demo
{
    Guid id;
    public Demo(Guid id) { this.id = id; }
    public override bool Equals(object obj)
    {
        return Equals(obj as Demo); //if objects are of non-comparable types, obj will be converted to null
    }
    public bool Equals(Demo obj)
    {
        if (obj == null)
        {
            return false;
        }
        else
        {
            return id.Equals(obj.id);
        }
    }
    //if two objects are Equal their hashcodes must be equal
    //however, if two objects hash codes are equal it is not necessarily true that the objects are equal
    //i.e. equal objects are a subset of equal hashcodes
    //more info here: https://stackoverflow.com/a/371348/361842
    public override int GetHashCode()
    {
        return id.GetHashCode();
    }
}

class Demo2
{
    Guid id;
    public Demo2(Guid id)
    {
        this.id = id;
    }

    public static bool operator ==(Demo2 obj1, Demo2 obj2)
    {
        if (ReferenceEquals(null, obj1)) 
        {
            return ReferenceEquals(null, obj2); //true if both are null; false if only obj1 is null
        }
        else
        {
            if(ReferenceEquals(null, obj2)) 
            {
                return false; //obj1 is not null, obj2 is; therefore false
            }
            else
            {
                return obj1.id == obj2.id; //return true if IDs are the same; else return false
            }
        }
    }

    // NB: We also HAVE to override this as below if overriding the == operator; this is enforced by the compiler.  However, oddly we could choose to override it different to the below; but typically that would be a bad idea...
    public static bool operator !=(Demo2 obj1, Demo2 obj2)
    {
        return !(obj1 == obj2);
    }
}

-3

Equals()অন্তর্নিহিত ধরণের (মান / রেফারেন্স) উপর নির্ভর করে হ্যাশ কোড বা সমতা ReferenceEquals()জন্য অনুসন্ধান করে এবং সর্বদা হ্যাশ কোডের জন্য যাচাই করা হয়। উভয় বস্তু একই মেমরি অবস্থানের দিকে নির্দেশ করলে ReferenceEqualsফেরত দেয় true

double e = 1.5;
double d = e;
object o1 = d;
object o2 = d;

Console.WriteLine(o1.Equals(o2)); // True
Console.WriteLine(Object.Equals(o1, o2)); // True
Console.WriteLine(Object.ReferenceEquals(o1, o2)); // False

Console.WriteLine(e.Equals(d)); // True
Console.WriteLine(Object.Equals(e, d)); // True
Console.WriteLine(Object.ReferenceEquals(e, d)); // False

4
এটা অপদার্থ. সমান বা রেফারেন্সক্যুয়াল উভয়ই হ্যাশকোডের দিকে তাকায় না। এখানে কেবল একটি প্রয়োজন আছে যে হ্যাশকোডস সমান অবজেক্টের সমান হওয়া উচিত। এবং অবজেক্টগুলি কোথাও ইঙ্গিত দেয় না ... রেফারেন্সএকোয়ালগুলি সত্য এবং যদি এর উভয় যুক্তি একই রেফারেন্স অবজেক্ট হয় বা উভয়ই নাল হয়।
জিম বাল্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.