আমি অসীম পুনরাবৃত্তি ছাড়াই কোনও '==' অপারেটর ওভারলোডের নালগুলির জন্য কীভাবে চেক করব?


113

নিম্নলিখিতটি == অপারেটর ওভারলোড পদ্ধতিতে অসীম পুনরাবৃত্তি ঘটায়

    Foo foo1 = null;
    Foo foo2 = new Foo();
    Assert.IsFalse(foo1 == foo2);

    public static bool operator ==(Foo foo1, Foo foo2) {
        if (foo1 == null) return foo2 == null;
        return foo1.Equals(foo2);
    }

আমি নালদের জন্য কীভাবে চেক করব?

উত্তর:


138

ব্যবহার ReferenceEquals:

Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);

public static bool operator ==(Foo foo1, Foo foo2) {
    if (object.ReferenceEquals(null, foo1))
        return object.ReferenceEquals(null, foo2);
    return foo1.Equals(foo2);
}

এই সমাধানটি কাজ করে নাAssert.IsFalse(foo2 == foo1);
এফআইএল

এবং এর foo1.Equals(foo2)অর্থ কী , উদাহরণস্বরূপ, আমি foo1 == foo2কেবল যদি চাই foo1.x == foo2.x && foo1.y == foo2.y? এই উত্তর যদি উপেক্ষা যেখানে নন foo1 != nullকিন্তু foo2 == null?
ড্যানিয়েল

দ্রষ্টব্য: সহজ বাক্য গঠন সহ একই সমাধান:if (foo1 is null) return foo2 is null;
রেম

20

ওভারলোড পদ্ধতিতে আপত্তি করার জন্য কাস্ট করুন:

public static bool operator ==(Foo foo1, Foo foo2) {
    if ((object) foo1 == null) return (object) foo2 == null;
    return foo1.Equals(foo2);
}

1
যথাযথভাবে। উভয়ই (object)foo1 == nullবা foo1 == (object)nullবিল্ট-ইন ওভারলোডে যাবে ==(object, object)এবং ব্যবহারকারী-সংজ্ঞায়িত ওভারলোডে যাবে না ==(Foo, Foo)। এটি ঠিক পদ্ধতিতে ওভারলোড রেজোলিউশনের মতো।
জেপ্প স্টিগ নীলসন

2
ভবিষ্যতের দর্শনার্থীদের কাছে - স্বীকৃত উত্তরটি একটি ফাংশন, যা == অবজেক্টের কার্যকর করে। এটি মূলত গ্রহণযোগ্য উত্তরের মতোই, যার একটি নেতিবাচক দিক রয়েছে: এটির জন্য একটি castালাই প্রয়োজন। অভিযুক্ত উত্তর এইভাবে উচ্চতর।
মাফাই

1
@ মাফিআই কাস্ট সম্পূর্ণরূপে একটি সংকলন সময় অপারেশন। যেহেতু সংকলক জানে যে কাস্ট ব্যর্থ হতে পারে না, তাই রানটাইমের সময় কিছু পরীক্ষা করার দরকার নেই। পদ্ধতির মধ্যে পার্থক্যগুলি সম্পূর্ণ নান্দনিক।
পরিবেশন করুন


4

চেষ্টা Object.ReferenceEquals(foo1, null)

যাইহোক, আমি ==অপারেটরকে ওভারলোড করার সুপারিশ করব না ; এটি রেফারেন্সগুলির তুলনা করার জন্য এবং Equals"শব্দার্থক" তুলনা করার জন্য ব্যবহার করা উচিত ।


4

যদি আমি ওভাররাইড করে bool Equals(object obj)ফেলেছি এবং আমি অপারেটরটি চাই ==এবং Foo.Equals(object obj)একই উত্তরটি ফিরে আসতে চাই, তবে আমি সাধারণত !=অপারেটরটিকে এভাবে প্রয়োগ করি :

public static bool operator ==(Foo foo1, Foo foo2) {
  return object.Equals(foo1, foo2);
}
public static bool operator !=(Foo foo1, Foo foo2) {
  return !object.Equals(foo1, foo2);
}

অপারেটর ==তারপরে আমার জন্য সমস্ত নাল চেক করার পরে কল করবে foo1.Equals(foo2)যে আমি যদি দুটি সমান হয় তবে প্রকৃত চেক করতে ওভাররাইড করেছি।


এটি খুব উপযুক্ত বোধ করে; Object.Equals(Object, Object)পাশাপাশি বাস্তবায়নের দিকে তাকিয়ে Object.ReferenceEquals(Object, Object), এটি বেশ স্পষ্ট যে Object.Equals(Object, Object)বাক্সের বাইরে অন্যান্য উত্তরের পরামর্শ অনুসারে সবকিছু করে। কেন ব্যবহার করবেন না?
tne

@ টেন কারণ ==অপারেটরকে ওভারলোড করার কোনও অর্থ নেই যদি আপনি চান সমস্ত ডিফল্ট আচরণ। আপনার যখন কেবলমাত্র কাস্টম তুলনা যুক্তি প্রয়োগ করতে হবে, অর্থাত্, কোনও রেফারেন্স সাম্যতা যাচাইয়ের চেয়ে বেশি কিছু করা উচিত।
ড্যান বেচার্ড

@ ডান আমি নিশ্চিত যে আপনি আমার বক্তব্য ভুল বুঝেছেন; এমন একটি প্রসঙ্গে যেখানে এটি ইতিমধ্যে প্রতিষ্ঠিত হয়েছে যে ওভারলোডিং ==কাঙ্ক্ষিত (প্রশ্নটি ইঙ্গিত করে) আমি কেবল এই উত্তরটি সমর্থন করে বলছি যা Object.Equals(Object, Object)অন্যান্য কৌশলগুলি যেমন ReferenceEqualsস্পষ্ট ক্যাসেটগুলি ব্যবহার বা অপ্রয়োজনীয় তৈরির মতো করে তোলে (সুতরাং "কেন এটি ব্যবহার করবেন না?", "এটি" হচ্ছে Equals(Object, Object))। এমনকি যদি আপনার সম্পর্কটি সম্পর্কহীনও হয় তবে সঠিক এবং আমি আরও এগিয়ে যাব: কেবলমাত্র ==বস্তুর জন্য আমরা ওভারলোডকে "মান বস্তু" হিসাবে শ্রেণিবদ্ধ করতে পারি।
tne

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

@tne ভার্চুয়াল পদ্ধতি কল নিখুঁত এর intricacies সম্পর্কে আরো তথ্যের জন্য, পড়ুন stackoverflow.com/questions/530799/...
ড্যান বেচার্ড

3

আপনি যদি সি # 7 ব্যবহার করেন বা তারপরে আপনি নাল ধ্রুবক প্যাটার্ন ম্যাচটি ব্যবহার করতে পারেন:

public static bool operator==(Foo foo1, Foo foo2)
{
    if (foo1 is null)
        return foo2 is null;
    return foo1.Equals(foo2);
}

এটি আপনাকে একটি কলিং অবজেক্টের চেয়ে সামান্যতম কোড দেয় e রেফারেন্সইকুয়ালস (foo1, নাল)


2
বাpublic static bool operator==( Foo foo1, Foo foo2 ) => foo1?.Equals( foo2 ) ?? foo2 is null;
ডানকো দুর্বিć

3

এক্ষেত্রে প্রকৃতপক্ষে চেক করার একটি সহজ উপায় রয়েছে null:

if (foo is null)

এটাই!

এই বৈশিষ্ট্যটি সি # 7 এ চালু হয়েছিল


@ ইলিয়াসার শুকরিয়া প্রশ্নগুলির মেয়াদ শেষ হওয়ার তারিখ নেই :)
গ্রোভেলপ্লেক্স

1

আমার পদ্ধতির করণীয়

(object)item == null

যার উপর আমি নির্ভর করছি objectনিজের ইক্যুয়ালিটি অপারেটর যা ভুল হতে পারে না। বা একটি কাস্টম এক্সটেনশন পদ্ধতি (এবং একটি ওভারলোড):

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null;
}

public static bool IsNull<T>(this T? obj) where T : struct
{
    return !obj.HasValue;
}

বা আরও কেসগুলি পরিচালনা করতে হতে পারে:

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null || obj == DBNull.Value;
}

সীমাবদ্ধতা IsNullমান ধরণের প্রতিরোধ করে। এখন এটি কলিং হিসাবে মিষ্টি

object obj = new object();
Guid? guid = null; 
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error

যার অর্থ আমার কাছে নালাগুলি জুড়ে যাচাই করার একটি ধারাবাহিক / না-ত্রুটি-প্রবণ স্টাইল রয়েছে। আমি এটির (object)item == nullচেয়ে খুব সামান্য দ্রুতগতিতেওObject.ReferenceEquals(item, null) পেয়েছি , তবে কেবল এটির জন্য যদি (আমি বর্তমানে এমন কিছু বিষয়ে কাজ করছি যেখানে আমি সবকিছুকে মাইক্রো-অনুকূলিত করতে পারি!)।

সাম্যতার চেক প্রয়োগের সম্পূর্ণ গাইড দেখতে , একটি রেফারেন্স ধরণের দুটি উদাহরণের তুলনা করার জন্য "সেরা অনুশীলন" কী?


নিতপিক: তুলনা করার মতো বৈশিষ্ট্যগুলিতে ঝাঁপ দেওয়ার আগে পাঠকদের তাদের নির্ভরতা লক্ষ্য করা উচিত DbNull, আইএমও যেখানে এসআরপি সম্পর্কিত বিষয়গুলি উত্পন্ন করে না তা বেশ বিরল। কোড গন্ধ যদিও কেবল পয়েন্ট করা, এটি খুব ভাল উপযুক্ত হতে পারে।
tne

0

স্থির Equals(Object, Object)পদ্ধতিটি দুটি বস্তু objAএবং objB, সমান কিনা তা নির্দেশ করে । এটি আপনাকে এমন বস্তুগুলি পরীক্ষা করতে সক্ষম করে যার nullসমতার জন্য মূল্য । এটি তুলনা করে objAএবংobjB সমতা জন্য:

  • এটি নির্ধারণ করে যে দুটি বস্তু একই বস্তুর রেফারেন্স উপস্থাপন করে কিনা। তারা যদি করে তবে পদ্ধতিটি ফিরে আসে true। এই পরীক্ষাটি ReferenceEqualsপদ্ধতিটি কল করার সমতুল্য । তদ্ব্যতীত, উভয় objAএবং যদি objBহয় null, পদ্ধতিটি ফিরে আসে true
  • এটা তোলে কিনা তা নির্ধারণ করে পারেন objAবা objBহয় null। যদি তা হয় তবে তা ফিরে আসে false। যদি দুটি অবজেক্ট একই অবজেক্টের রেফারেন্স উপস্থাপন না করে এবং না হয় তবে nullএটি কল objA.Equals(objB)করে ফলাফলটি প্রদান করে। এর অর্থ এটি যদি objAওভাররাইড করেObject.Equals(Object) পদ্ধতিটি এই ওভাররাইডকে বলা হয়।

public static bool operator ==(Foo objA, Foo objB) {
    return Object.Equals(objA, objB);
}

0

ওভাররাইডিং অপারেটরের আরও উত্তর দেওয়া কীভাবে নাল সাথে তুলনা করতে হয় যে এখানে নকল হিসাবে পুনঃনির্দেশ করে।

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

এটি ওভারলোড ==,! =, সমান এবং গেটহ্যাশকোড হবে

    public static bool operator !=(ValueObject self, ValueObject other) => !Equals(self, other);
    public static bool operator ==(ValueObject self, ValueObject other) => Equals(self, other);
    public override bool Equals(object other) => Equals(other as ValueObject );
    public bool Equals(ValueObject other) {
        return !(other is null) && 
               // Value comparisons
               _value == other._value;
    }
    public override int GetHashCode() => _value.GetHashCode();

আরও জটিল বস্তুর জন্য সমানতে আরও সমৃদ্ধ এবং আরও সমৃদ্ধ গেটহ্যাশকোড যুক্ত করুন।


0

একটি আধুনিক এবং ঘনীভূত সিনট্যাক্সের জন্য:

public static bool operator ==(Foo x, Foo y)
{
    return x is null ? y is null : x.Equals(y);
}

public static bool operator !=(Foo x, Foo y)
{
    return x is null ? !(y is null) : !x.Equals(y);
}

-3

অপারেটর overloads একটি সাধারণ ত্রুটি == ব্যবহার করা (a == b), (a ==null)অথবা (b == null)রেফারেন্স সমতার জন্য বার করো। এর পরিবর্তে অতিরিক্ত লোড অপারেটর == কে কল করার ফলস্বরূপ , এটি ঘটে infinite loopReferenceEqualsলুপটি এড়ানোর জন্য অবজেক্টে টাইপটি ব্যবহার বা কাস্ট করুন।

এটা পরীক্ষা করো

// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals
{
    return true;
}

// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))// using casting the type to Object
{
    return false;
}

রেফারেন্স ওভারলোডিং নির্দেশিকা সমান () এবং অপারেটর ==


1
এই সমস্ত তথ্যের সাথে ইতিমধ্যে একাধিক উত্তর রয়েছে। আমাদের একই উত্তরের 7 তম অনুলিপিটির প্রয়োজন নেই।
পরিবেশন করুন

-5

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

public static bool operator ==(Foo foo1, Foo foo2)
{
    //  check if the left parameter is null
    bool LeftNull = false;
    try { Type temp = a_left.GetType(); }
    catch { LeftNull = true; }

    //  check if the right parameter is null
    bool RightNull = false;
    try { Type temp = a_right.GetType(); }
    catch { RightNull = true; }

    //  null checking results
    if (LeftNull && RightNull) return true;
    else if (LeftNull || RightNull) return false;
    else return foo1.field1 == foo2.field2;
}

আপনার যদি অনেক নাল অবজেক্ট থাকে তবে ব্যতিক্রম হ্যান্ডলিং বড় ওভারহেড হতে পারে।
ক্যাসপ্রজল

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