কেন সি # দুটি বস্তুর প্রকার একে অপরের সাথে তুলনা করতে ব্যর্থ হয় তবে ভিবি তা করে না?


152

সি # তে আমার দুটি জিনিস রয়েছে এবং এটি বুলিয়ান বা অন্য কোনও ধরণের কিনা তা আমি জানি না। তবে আমি যখন সেই সিটি তুলনা করার চেষ্টা করি তখন # সঠিক উত্তর দিতে ব্যর্থ হয়। আমি VB.NET এর সাথে একই কোডটি চেষ্টা করেছি এবং এটি এটি করেছে!

কেউ যদি আমাকে বলতে পারে যে কোনও সমাধান আছে তবে এটি কীভাবে ঠিক করবেন?

সি #:

object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!

VB.NET:

Dim a As Object = True
Dim b As Object = True
Dim c As Object = False
If (a = b) Then c = True
MessageBox.Show(c.ToString()) '// Outputs True

3
আপনি যদি সাম্যের তুলনাকারীর সাথে পরিবর্তন করেন a.Equals(b)?
জেসন মেকলে

8
শিক্ষাগত উদ্দেশ্যগুলির জন্য এটি একটি ভাল প্রশ্ন।
লোবো

10
কারণ আপনার ভিবি.এনইটি কোডটি আপনার সি # কোডের সমান নয়।
সুরক্ষা মাউন্ট

9
যখন আপনি নির্ধারিত হন তখন aবক্সিং পাবেন এবং এতে একটি বাক্স থাকবে true। আপনি নির্ধারিত যখন bআপনি পেতে অন্য বক্স এছাড়াও ধারণকারী true। আপনি যখন তুলনা করেন aএবং b, কারণ উভয়ই সংকলন-টাইপ ধরণের object, আপনি operator ==(object, object)সি # ভাষা নির্দিষ্টকরণ দ্বারা সংজ্ঞায়িত ওভারলোডটিকে কল করেন । রেফারেন্সগুলি একই অবজেক্টে যায় কিনা তা এই ওভারলোড পরীক্ষা করে। যেহেতু আপনার দুটি বাক্স রয়েছে, ফলস্বরূপ false, এবং "নীচে" আপনার বিবৃতিটি ifচলবে না। এটি আরও ভালভাবে বুঝতে, এইটির কার্যভারটি পরিবর্তন করার চেষ্টা করুন b: object b = a;এখন আপনার কাছে কেবল একটি বাক্স রয়েছে।
জেপ্পে স্টিগ নীলসেন

3
আমি আগে বলার আগে
কিছুটা সময় পেয়েছিলাম

উত্তর:


168

সি # তে, ==অপারেটর (যখন রেফারেন্স টাইপের এক্সপ্রেশনগুলিতে প্রয়োগ করা হয়) এটি ওভারলোড না হওয়া পর্যন্ত একটি রেফারেন্স সমতা পরীক্ষা করে । আপনি দুটি রেফারেন্সের সাথে তুলনা করছেন যা বক্সিং রূপান্তরগুলির ফলাফল, সুতরাং সেগুলি স্বতন্ত্র রেফারেন্স।

সম্পাদনা: যে ধরণের ওভারলোড এর সাথে ==, আপনি আলাদা আচরণ পেতে পারেন - তবে এটি সংকলন-টাইমের এক্সপ্রেশনগুলির উপর ভিত্তি করে । উদাহরণস্বরূপ, stringসরবরাহ করে ==(string, string):

string x = new string("foo".ToCharArray());
string y = new string("foo".ToCharArray());
Console.WriteLine(x == y); // True
Console.WriteLine((object) x == (object) y); // False

এখানে প্রথম তুলনা ওভারলোডেড অপারেটরটি ব্যবহার করছে তবে দ্বিতীয়টি "ডিফল্ট" রেফারেন্স তুলনা ব্যবহার করছে।

ভিবিতে =অপারেটর আরও অনেক বেশি কাজ করে - এটি এমনকি ব্যবহারের সমতুল্য নয় object.Equals(x, y), যেমন জিনিসগুলি Option Compareকীভাবে পাঠ্যের তুলনা করা যায় তা প্রভাবিত করতে পারে।

মৌলিকভাবে অপারেটররা একইভাবে কাজ করে না এবং একইভাবে কাজ করার উদ্দেশ্যে নয় ।


17
+1 আমি জানতাম আপনি আশেপাশে থাকবেন, আপনি এই ধরণের রহস্যময় প্রশ্ন পছন্দ করেন :)
আবদুসালাম বেন হাজ

3
@ আবজি: আমি আশাবাদী যে ভিবিতে কী করেছে তার আরও বিশদ বিবরণ দিতে সক্ষম হব, তবে অনুমানটি মারাত্মকভাবে =পরিষ্কার নয়।
জন স্কিটি

আকর্ষণীয় জিনিস, কিন্তু গতিশীল অবজেক্ট পরিবর্তন করা ভিবি হিসাবে একই আচরণ করে
ভ্ল্যাডএল

4
@ ভ্ল্যাডএল: হ্যাঁ, কারণ তখন এটি কার্যকর হবে-সময় ধরণের, এবং bool == boolতুলনা সম্পাদন করবে ।
জন স্কিটি

1
@ মাহদী লোবো কোড সরবরাহ করেছেন, তবে তার উত্তরও ভুল, জনের মতো নয়।
পরিবেশন করুন

79

জনের উত্তর ছাড়াও যা সি এর # টি দিক সম্পর্কে ব্যাখ্যা করে, এখানে ভিবি কী করে:

ভিবিতে Option Strict On, একটি তুলনা = সর্বদা মান সমতার জন্য পরীক্ষা করে এবং কখনও রেফারেন্স সমতার জন্য নয়। প্রকৃতপক্ষে, আপনার কোডটি আপনি একবার স্যুইচ করলেও এটি সংকলন করে না Option Strict Onকারণ System.Objectকোনওটি সংজ্ঞায়িত করে না Operator=। আপনার সবসময় এই বিকল্পটি থাকা উচিত , এটি একটি ভেনাস ফ্লাইট্র্যাপের চেয়ে বেশি কার্যকরভাবে বাগগুলি ধরে (যদিও আপনার নির্দিষ্ট ক্ষেত্রে এই শিথিল আচরণটি আসলে সঠিক কাজ করে)। 1

প্রকৃতপক্ষে, Option Strict Onভিবি সি # এর চেয়েও কঠোর আচরণ করে: সি # তে, a == b হয় কল কল করে SomeType.operator==(a, b)বা এটি উপস্থিত না থাকলে রেফারেন্স সমতা তুলনা (যা কল করার সমতুল্য object.ReferenceEquals(a, b)) প্রার্থনা করে ।

অন্যদিকে ভিবিতে, তুলনাটি a = b সর্বদা সমতা অপারেটরকে অনুরোধ করে। 2 আপনি যদি রেফারেন্সের সমতা তুলনাটি ব্যবহার করতে চান তবে আপনাকে ব্যবহার করতে হবে a Is b(যা আবার, একই হিসাবে Object.ReferenceEquals(a, b))।


1) এখানে ব্যবহারের Option Strict Offজন্য একটি খারাপ ধারণা কেন এটি একটি ভাল ইঙ্গিত : আমি প্রায় এক দশক ধরে ভিবি.এনইটি ব্যবহার করেছি, নেট থেকে আনুষ্ঠানিক প্রকাশের আগে কয়েক বছর আগে পর্যন্ত, এবং এর সাথে কী হয় তা আমার ঠিক কোনও ধারণাa = b নেই Option Strict Off। এটি এক ধরণের সাম্যতা তুলনা করে তবে ঠিক কী হয় এবং কেন, কোনও ধারণা নেই। এটি সি # এর dynamicবৈশিষ্ট্যের চেয়ে জটিল , যদিও (কারণ এটি একটি ভাল-ডকুমেন্টেড এপিআইয়ের উপর নির্ভর করে)। এমএসডিএন যা বলেছে তা এখানে:

যেহেতু শক্তিশালী টাইপিংOption Strict On সরবরাহ করে , ডেটা হ্রাসের সাথে অযৌক্তিক ধরণের রূপান্তরগুলি রোধ করে , দেরী বন্ধনটিকে অস্বীকার করে এবং কার্যকারিতা উন্নত করে, এর ব্যবহার দৃ strongly়ভাবে সুপারিশ করা হয়।

2) জন একটি ব্যতিক্রম, স্ট্রিং উল্লেখ করেছে, যেখানে সাম্যের তুলনা পিছনের সামঞ্জস্যের কারণে আরও কিছু কাজ করে।


4
+1 টি। আমি মনে করি এটি এমন একটি ক্ষেত্রে যেখানে ভিবি.এনইটি ডিজাইনাররা ভিবি 6 এবং ভিবিএ থেকে আগত প্রোগ্রামারদের ভাষাকে "কেবলমাত্র কাজ" করতে সফল হয়েছিল, যেখানে ওওপি অনেক কম বিশিষ্ট এবং তাই রেফারেন্স সমতার ধারণাটি খুব কম গুরুত্বপূর্ণ। একটি ভিবি কোডার অবজেক্টস ইত্যাদির বিষয়ে বেশি চিন্তা না করে ভাল ওয়ার্কিং কোড লিখতে পারে।
জন এম গ্যান্ট

5
+1 এটি যতটা করা উচিত ঠিক ততটা উজ্জ্বল নয়। ব্যবহার না করা Option Strict Onএকটি ফৌজদারি অপরাধ হিসাবে বিবেচনা করা উচিত ...
হরিণ হান্টার

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

4

অবজেক্টের উদাহরণগুলি অপারেটরের সাথে তুলনা করা হয় না "=="। আপনার "সমান" পদ্ধতি ব্যবহার করা উচিত। "==" অপারেটরের সাথে রেফারেন্সগুলির তুলনা করা হচ্ছে, বস্তু নয়।

এটা চেষ্টা কর:

public class MyObject
{
    public MyObject(String v)
    {
        Value = v;
    }
    public String Value { get; set; }
}

MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
    Debug.WriteLine("a reference is equal to b reference");
}else{
    Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
    Debug.WriteLine("a object is equal to b object");
} else {
    Debug.WriteLine("a object is not equal to b object");
}

ফলাফল:

a reference is not equal to b reference
a object is not equal to b object

এখন, এই চেষ্টা করুন:

public class MyObject
{
    public MyObject(String v)
    {
        Value = v;
    }
    public String Value { get; set; }

    public bool Equals(MyObject o)
    {
        return (Value.CompareTo(o.Value)==0);
    }
}
MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
    Debug.WriteLine("a reference is equal to b reference");
}else{
    Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
    Debug.WriteLine("a object is equal to b object");
} else {
    Debug.WriteLine("a object is not equal to b object");
}

ফলাফল:

a reference is not equal to b reference
a object is equal to b object

1
এটি কেবল কারণ আপনি ওভাররাইড করেন নি operator ==। আপনি যদি সেই অপারেটরটিকে ওভাররড করেন এবং না সমান হয় তবে আপনার আউটপুটটি বিপরীত হবে। রেফারেন্সের সাথে তুলনা করার অন্তর্নিহিত কিছুই নেই operator ==এবং মানগুলির তুলনা করার সাথে অন্তর্নিহিত কিছুই নেই Equals। তারা সমতা নির্ধারণের দুটি উপায়; উভয় একটি রেফারেন্স তুলনা ডিফল্ট বাস্তবায়ন আছে, এবং উভয় আপনি যা করতে চান তা করতে ওভাররাইড করা যেতে পারে। কেবলমাত্র অন্য পার্থক্যটি হ'ল Equalsভার্চুয়াল, এবং operator ==তা নয়।
পরিবেশন

1
@ সার্ভি: নোট করুন যে আপনি ওভাররাইড করতে পারবেন না ==- আপনি কেবল এটি ওভারলোড করতে পারবেন ।
জন স্কিটি

1
দুঃখিত, -1। এই উত্তরটি কেবল ভুল এবং এটি গ্রহণযোগ্য হওয়া উচিত নয়।
কনরাড রুডলফ

কোথাও কোথাও একটি জাভা প্রশ্ন রয়েছে যা এই উত্তরের জন্য অপেক্ষা করছে।
চাদ শোগগিনস

3

সমস্যাটি হ'ল সি # এর অপারেটরটি একটি স্ট্যাটিক পদ্ধতিতে কল (ভাল, সম্ভবত প্রযুক্তিগতভাবে নয়, তবে এটি এমনটি হতে পারে) দুটি প্যারামিটারের টাইপ টাইপের টাইপের ভিত্তিতে। এই বিষয়গুলির আসল রানটাইম ধরণের কী তা বিবেচনাধীন নয়।

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

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

আপনার কোড বুলিয়ান মান ধারণ করে, কিন্তু তারা যে ভেরিয়েবল ধরনের হয় object। কারণ পরিবর্তনশীল ধরনের হয় object, সি # কম্পাইলার ব্যবহার objectবাস্তবায়ন ==, যা তুলনা রেফারেন্স বস্তু নয় দৃষ্টান্ত। যেহেতু বুলিয়ান মানগুলি বাক্স, তাই তাদের মানগুলি একই হলেও তাদের একই রেফারেন্স নেই।

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


এটি সি # এর জন্য দুর্দান্ত দেখাচ্ছে; আমি =নিশ্চিতভাবে বলতে ভিবিতে কি করে তা সম্পর্কে আমি যথেষ্ট জানি না ।
জন স্কিটি

@ জোনস্কিট মেলা যথেষ্ট।
12:25 এ

প্রতি msdn.microsoft.com/en-us/library/cey92b0t(v=vs.110).aspx , বিভাগে "রিলেশনাল তুলনা অপারেটরদের সঙ্গে Typeless প্রোগ্রামিং": =যেমন সব অন্যান্য রিলেশনাল তুলনা অপারেটরদের সঙ্গে বরাবর <, >=ইত্যাদি , অপারেটরের উভয় বা উভয় দিক থাকলে বিশেষ চিকিত্সা দেওয়া হয় Object। এই বিশেষ চিকিত্সাটি করা হয় যাতে ভিবি 6 প্রোগ্রামাররা, যারা Variantপ্রাক-নেট ভিবি হিসাবে পরিচিত একটি প্রকারের ব্যবহারে অভ্যস্ত , Objectতারা Variantআগে যেভাবে ভিবি.নেট ব্যবহার করেছেন সেগুলি ব্যবহার করতে পারেন ।
আরএসকর

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