অপারেটর == সি # তে জেনেরিক ধরণের ক্ষেত্রে প্রয়োগ করা যাবে না?


326

এমএসডিএন-তে== অপারেটরের ডকুমেন্টেশন অনুসারে ,

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

তাহলে এই কোড স্নিপেট সংকলন করতে ব্যর্থ হয় কেন?

bool Compare<T>(T x, T y) { return x == y; }

আমি ত্রুটি পেয়েছি অপারেটর '==' 'টি' এবং 'টি' টাইপের অপারেন্ডগুলিতে প্রয়োগ করা যাবে না । আমি ভাবছি কেন, যেহেতু আমি বুঝতে পারি ==অপারেটরটি সমস্ত প্রকারের জন্য পূর্বনির্ধারিত?

সম্পাদনা: ধন্যবাদ, সবাই। আমি প্রথমে লক্ষ্য করিনি যে বিবৃতিটি কেবল রেফারেন্সের ধরণের ছিল। আমি আরও ভেবেছিলাম যে বিট-বাই-বিট তুলনাটি সমস্ত মানের ধরণের জন্য সরবরাহ করা হয়, যা আমি জানি এখন সঠিক নয়

তবে, আমি যদি কোনও রেফারেন্স টাইপ ব্যবহার করছি, ==অপারেটরটি কি পূর্বনির্ধারিত রেফারেন্স তুলনা ব্যবহার করবে, বা কোনও টাইপ সংজ্ঞায়িত হলে অপারেটরের ওভারলোডেড সংস্করণটি ব্যবহার করবে?

সম্পাদনা 2: ট্রায়াল এবং ত্রুটির মাধ্যমে, আমরা শিখেছি যে ==অপারেটর একটি সীমাহীন জেনেরিক টাইপ ব্যবহার করার সময় পূর্বনির্ধারিত রেফারেন্স তুলনা ব্যবহার করবে। প্রকৃতপক্ষে, সংকলকটি সীমাবদ্ধ ধরণের আর্গুমেন্টের জন্য এটি খুঁজে পেতে পারে এমন সর্বোত্তম পদ্ধতিটি ব্যবহার করবে তবে এটি আর দেখবে না। উদাহরণস্বরূপ, নীচের কোডটি সর্বদা মুদ্রণ করবে true, এমনকি যখন Test.test<B>(new B(), new B())বলা হয়:

class A { public static bool operator==(A x, A y) { return true; } }
class B : A { public static bool operator==(B x, B y) { return false; } }
class Test { void test<T>(T a, T b) where T : A { Console.WriteLine(a == b); } }

আপনার ফলোআপ প্রশ্নের উত্তরের জন্য আমার উত্তরটি আবার দেখুন।
জিওভান্নি গাল্বো

এটি জেনে রাখা কার্যকর হতে পারে যে জেনারিক ব্যতীত, কিছু প্রকারের জন্য ==একই ধরণের দুটি অপারেন্ডের মধ্যে অনুমোদিত নয় the এটি structপ্রকারের জন্য সত্য ("পূর্বনির্ধারিত" প্রকারগুলি ব্যতীত) যা ওভারলোড করে না operator ==। একটি সাধারণ উদাহরণ হিসাবে, এটি ব্যবহার করে দেখুন:var map = typeof(string).GetInterfaceMap(typeof(ICloneable)); Console.WriteLine(map == map); /* compile-time error */
জেপ্পে স্টিগ নীলসন

আমার নিজের পুরানো মন্তব্য অবিরত। উদাহরণস্বরূপ ( অন্যান্য থ্রেড দেখুন ) এর সাথে var kvp1 = new KeyValuePair<int, int>(); var kvp2 = kvp1;, তবে আপনি চেক করতে পারবেন না kvp1 == kvp2কারণ KeyValuePair<,>এটি কাঠামো, এটি কোনও সি # পূর্বনির্ধারিত টাইপ নয় এবং এটি ওভারলোডও করে না operator ==। তবুও একটি উদাহরণ দেওয়া হয়েছে var li = new List<int>(); var e1 = li.GetEnumerator(); var e2 = e1;যার সাহায্যে আপনি না করতে পারেন e1 == e2(এখানে আমাদের নেস্টেড স্ট্রাক্ট রয়েছে List<>.Enumerator( "List`1+Enumerator[T]"রানটাইম দ্বারা ডাকা ) যা ওভারলোড না করে ==)।
জেপ্প স্টিগ নীলসেন

পুনরায়: "তাহলে এই কোড স্নিপেট সংকলন করতে ব্যর্থ হয় কেন?" - এর ... কারণ আপনি কোনও boolথেকে ফিরে আসতে পারবেন না void...
ব্রেইনস্লাগস 83

1
@ BrainSlugs83 10 বছরের পুরানো বাগটি ধরার জন্য ধন্যবাদ!
হোসাম অলি

উত্তর:


143

"... পূর্বনির্ধারিত এবং ব্যবহারকারী-সংজ্ঞায়িত রেফারেন্স উভয় প্রকারের জন্য ডিফল্টরূপে == উপরে বর্ণিত হিসাবে আচরণ করে" "

টাইপ টি অগত্যা কোনও রেফারেন্স টাইপ নয়, তাই সংকলক সেই অনুমানটি করতে পারে না।

তবে এটি সংকলন করবে কারণ এটি আরও স্পষ্ট:

    bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }

অতিরিক্ত প্রশ্ন অনুসরণ করুন, "তবে আমি যদি কোনও রেফারেন্স টাইপ ব্যবহার করছি, তবে == অপারেটর কি পূর্বনির্ধারিত রেফারেন্স তুলনা ব্যবহার করবে, বা কোনও প্রকারের সংজ্ঞা দেওয়া থাকলে অপারেটরের ওভারলোড হওয়া সংস্করণটি ব্যবহার করবে?"

আমি ভেবেছিলাম যে == জেনেরিক্সে ওভারলোড হওয়া সংস্করণটি ব্যবহার করা হবে তবে নিম্নলিখিত পরীক্ষাটি অন্যথায় প্রদর্শন করে। আকর্ষণীয় ... আমি কেন জানতে চাই! যদি কেউ জানেন তবে শেয়ার করুন

namespace TestProject
{
 class Program
 {
    static void Main(string[] args)
    {
        Test a = new Test();
        Test b = new Test();

        Console.WriteLine("Inline:");
        bool x = a == b;
        Console.WriteLine("Generic:");
        Compare<Test>(a, b);

    }


    static bool Compare<T>(T x, T y) where T : class
    {
        return x == y;
    }
 }

 class Test
 {
    public static bool operator ==(Test a, Test b)
    {
        Console.WriteLine("Overloaded == called");
        return a.Equals(b);
    }

    public static bool operator !=(Test a, Test b)
    {
        Console.WriteLine("Overloaded != called");
        return a.Equals(b);
    }
  }
}

আউটপুট

ইনলাইন: ওভারলোডড == ডাকা হয়েছে

জেনেরিক:

চালু রাখবার জন্য যেকোনো বোতাম চাপুন . । ।

অনুসরণ করুন 2

আমি এটি উল্লেখ করতে চাই না যে আমার তুলনা পদ্ধতিতে পরিবর্তন করে

    static bool Compare<T>(T x, T y) where T : Test
    {
        return x == y;
    }

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


ধন্যবাদ। আমি লক্ষ্য করিনি যে বিবৃতিটি কেবল রেফারেন্সের ধরণের ছিল।
হোসাম অলি

4
পুনঃ অনুসরণ করুন 2: আসলে সংকলক এটি এটি খুঁজে পাওয়া সেরা পদ্ধতির সাথে লিঙ্ক করবে, যা এই ক্ষেত্রে টেস্ট.অপ_একুয়াল। তবে যদি আপনার কাছে এমন কোনও ক্লাস থাকে যা টেস্ট থেকে উদ্ভূত হয় এবং অপারেটরটিকে ওভাররাইড করে, তবে টেস্টের অপারেটরটিকে এখনও ডাকা হবে।
হোসাম অলি

4
আমি ভাল অনুশীলন যেটি আমি উল্লেখ করতে চাই তা হ'ল আপনার সর্বদা একটি ওভাররাইড Equalsপদ্ধতিতে ( ==অপারেটরে নয়) ভিতরে প্রকৃত তুলনা করা উচিত ।
jpbochi

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

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

291

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

সমানকে কল করার পরিবর্তে এটি ব্যবহার করা ভাল IComparer<T>- এবং যদি আপনার কাছে আরও তথ্য না থাকে তবে EqualityComparer<T>.Defaultএটি একটি ভাল পছন্দ:

public bool Compare<T>(T x, T y)
{
    return EqualityComparer<T>.Default.Equals(x, y);
}

অন্য যে কোনও বিষয় বাদে, এটি বক্সিং / কাস্টিং এড়ায়।


ধন্যবাদ। আমি একটি সাধারণ মোড়কের ক্লাস লেখার চেষ্টা করছিলাম, তাই আমি কেবল প্রকৃত মোড়ানো সদস্যকে অপারেশনটি অর্পণ করতে চেয়েছিলাম। তবে ইক্যুয়ালিটি কম্পিউটারের বিষয়টি <T>। ডিফল্টটি অবশ্যই আমার কাছে মূল্য যুক্ত করেছে। :)
হোসাম অলি

নাবালক একদিকে, জন; আপনি আমার পোস্টে মন্তব্য পুনরায় pobox বনাম yoda নোট করতে চাইবেন।
মার্ক গ্র্যাভেল

4
ইক্যুয়ালিটি কম্পিউটার ব্যবহার করার জন্য
টিপসটি

1
এটি শূন্যের সাথে তুলনা করতে পারে এবং এটি অকার্যকর মান প্রকারের জন্য সর্বদা মিথ্যা বলে চিহ্নিত করার জন্য +1
জালাল

@ ব্লুরাজা: হ্যাঁ, কারণ নাল আক্ষরিকের সাথে তুলনা করার জন্য বিশেষ বিধি রয়েছে। সুতরাং "কোনও বাধা ছাড়াই আপনি নাল সাথে তুলনা করতে পারবেন তবে কেবল নাল"। এটি ইতিমধ্যে উত্তর আছে। সুতরাং, কেন এটি সঠিক হতে পারে না?
জন স্কিটি

41

সাধারণভাবে, EqualityComparer<T>.Default.Equalsকার্যকর করা এমন কোনও কিছু দিয়ে কাজ করা উচিত IEquatable<T>, বা এর বুদ্ধিমান Equalsবাস্তবায়ন রয়েছে।

তবে, যদি ==এবং Equalsকোনও কারণে আলাদাভাবে প্রয়োগ করা হয় তবে জেনেরিক অপারেটরগুলির বিষয়ে আমার কাজটি কার্যকর হওয়া উচিত; এটি (অন্যদের মধ্যে) অপারেটর সংস্করণগুলিকে সমর্থন করে :

  • সমান (টি মান 1, টি মান 2)
  • মানসম্পন্ন (টি মান 1, টি মান 2)
  • গ্রেটারথন (টি মান 1, টি মান 2)
  • লেসথান (টি মান 1, টি মান 2)
  • গ্রেটারথ্যানঅরকুয়াল (টি মান 1, টি মান 2)
  • লেসারথ্যানআরকুইয়াল (টি মান 1, টি মান 2)

খুব আকর্ষণীয় গ্রন্থাগার! :) (পার্শ্ব নোট: আমি www.yoda.arachsys.com লিঙ্কটি ব্যবহার করার পরামর্শ দিতে পারি, কারণ আমার কর্মক্ষেত্রে ফায়ারওয়াল দ্বারা পোবক্সটি ব্লক করা হয়েছিল? সম্ভবত অন্যরাও একই সমস্যার মুখোমুখি হতে পারে।)
হোসাম অলি

ধারণা যে pobox.com/~skeet হবে সবসময় এমনকি যদি এটি অন্য কোথাও চলে আসে - আমার ওয়েবসাইট বাতলান। আমি উত্তরসূরির জন্য পোক্সবক্স.কমের মাধ্যমে লিঙ্কগুলি পোস্ট করার প্রবণতা রাখি - তবে আপনি বর্তমানে এর পরিবর্তে yoda.arachsys.com প্রতিস্থাপন করতে পারেন ।
জন স্কিটে

পোবক্স.কমের সমস্যাটি হ'ল এটি একটি ওয়েব-ভিত্তিক ই-মেইল পরিষেবা (বা তাই সংস্থার ফায়ারওয়াল বলে) তাই এটি ব্লক করা আছে। সে কারণেই আমি এর লিঙ্কটি অনুসরণ করতে পারি না।
হোসাম অলি

"তবে, যদি, == এবং সমানগুলি কোনও কারণে আলাদাভাবে প্রয়োগ করা হয়" - পবিত্র ধূমপান! কি তবে! সম্ভবত আমার কেবল বিপরীতভাবে ব্যবহারের কেস দেখতে হবে, তবে ডাইভারজেন্ট সমান শব্দার্থবিজ্ঞান সহ একটি লাইব্রেরি সম্ভবত জেনেরিকের সাথে ঝামেলার চেয়ে আরও বড় সমস্যার মধ্যে চলে যাবে।
এডওয়ার্ড ব্রে

@ অ্যাডওয়ার্ড্রে আপনি ভুল করছেন না; সংকলক এটি প্রয়োগ করতে পারলে ভাল
লাগত

31

এতগুলি উত্তর, এবং একটিও কেন ব্যাখ্যা দেয় না? (যা জিওভানি স্পষ্টভাবে জিজ্ঞাসা করেছিলেন) ...

। নেট জেনারিকগুলি সি ++ টেম্পলেটগুলির মতো কাজ করে না। সি ++ টেম্পলেটগুলিতে, প্রকৃত টেম্পলেট প্যারামিটারগুলি জানা যাওয়ার পরে ওভারলোড রেজোলিউশন ঘটে।

.NET জেনেরিকসে (সি # সহ) প্রকৃত জেনেরিক পরামিতিগুলি না জেনে ওভারলোড রেজোলিউশন ঘটে। সংকলক কল করতে ফাংশনটি বেছে নিতে কেবলমাত্র তথ্যই জেনেরিক পরামিতিগুলিতে টাইপ সীমাবদ্ধতা থেকে আসে।


2
তবে কেন সংকলক তাদের জেনেরিক অবজেক্ট হিসাবে বিবেচনা করতে পারবেন না? ==সব ধরণের জন্য সমস্ত কাজ করার পরে তা রেফারেন্স প্রকার বা মান ধরণের হতে পারে। এটি এমন প্রশ্ন হওয়া উচিত যা আমি মনে করি না আপনি উত্তর দিয়েছেন।
নওফাল

4
@ নওফাল: আসলে না, ==সমস্ত মানের ধরণের জন্য কাজ করে না। আরও গুরুত্বপূর্ণ, এটি সমস্ত ধরণের জন্য একই অর্থ রাখে না, তাই সংকলকটি কী করতে পারে তা জানে না।
বেন ভয়েগট

1
বেন, ওহ হ্যাঁ আমি কোনও প্রকার ছাড়াই তৈরি করতে সক্ষম কাস্টম স্ট্রাক্টগুলি মিস করেছি ==। আপনি কি এই অংশটিকে নিজের উত্তরে অন্তর্ভুক্ত করতে পারেন কারণ আমি অনুমান করি যে
এটিই

12

সংকলন টি জানতে পারে না টি স্ট্রাক (মানের ধরণ) হতে পারে না। সুতরাং আপনাকে এটি বলতে হবে এটি কেবলমাত্র আমার মনে হয় রেফারেন্স প্রকারের হতে পারে:

bool Compare<T>(T x, T y) where T : class { return x == y; }

এটি কারণ যদি টি একটি মান ধরণের হতে পারে তবে এমন কিছু ক্ষেত্রে দেখা দিতে পারে যেখানে x == yঅসুস্থ হতে পারে - যখন কোনও ধরণের অপারেটর == সংজ্ঞায়িত না থাকে। এটির ক্ষেত্রেও এটি ঘটবে যা আরও সুস্পষ্ট:

void CallFoo<T>(T x) { x.foo(); }

এটিও ব্যর্থ হয়, কারণ আপনি কোনও টাইপ টি পাস করতে পারেন যাতে কোনও ফাংশন ফু থাকবে না। সি # আপনাকে সব ধরণের সম্ভাব্য প্রকারের সর্বদা একটি কার্যকারিতা রয়েছে তা নিশ্চিত করতে বাধ্য করে। এটি যেখানে ক্লজ দ্বারা সম্পন্ন হয়েছে।


1
স্পষ্টতার জন্য ধন্যবাদ। আমি জানতাম না যে মান ধরণেরগুলি বাক্সের বাইরে == অপারেটরকে সমর্থন করে না।
হোসাম অলি

1
হোসাম, আমি জিএমসিএস (মনো) দিয়ে পরীক্ষা করেছি এবং এটি সর্বদা উল্লেখগুলির সাথে তুলনা করে। (উদাহরণস্বরূপ এটি টির জন্য একটি বিকল্প হিসাবে সংজ্ঞায়িত অপারেটর ব্যবহার করে না ==)
জোহানেস স্কাউব -

এই সমাধান সহ একটি সতর্কতা রয়েছে: অপারেটর == ওভারলোড করা যায় না; এই স্ট্যাকওভারফ্লো প্রশ্নটি দেখুন
দিমিত্রি সি

8

শ্রেণিবদ্ধতা ব্যতীত এটি প্রদর্শিত হয়:

bool Compare<T> (T x, T y) where T: class
{
    return x == y;
}

এক উপলব্ধি করা উচিত যখন classসীমাবদ্ধ Equalsমধ্যে ==থেকে অপারেটর উত্তরাধিকারী Object.Equals, একটি struct ওভাররাইড যে যখন ValueType.Equals

মনে রাখবেন যে:

bool Compare<T> (T x, T y) where T: struct
{
    return x == y;
}

একই সংকলক ত্রুটিটি দেয়।

এখনও আমি বুঝতে পারি না যে কেন একটি মানের ধরণের সমতা অপারেটরের তুলনা করা কম্পাইলার দ্বারা প্রত্যাখ্যান করা হয়। আমি যদিও একটি বাস্তবতার জন্য জানি যে এটি কাজ করে:

bool Compare<T> (T x, T y)
{
    return x.Equals(y);
}

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

তবে আপনি যদি কোনও মানের ধরণে == করেন তবে মান ধরণের ক্ষেত্রে সেই অপারেটরটি কার্যকর করতে হবে না।
জোহানেস স্কাউব -

এটি বোধগম্য হবে, লিটব :) এটি সম্ভব যে ব্যবহারকারীর দ্বারা সংজ্ঞায়িত স্ট্রাইকগুলি ওভারলোড == না হয়, তাই সংকলক ব্যর্থ হয়।
জন লিমাজাপ

2
প্রথম তুলনা পদ্ধতিটি ব্যবহার করে নাObject.Equals বরং পরিবর্তে রেফারেন্সের সমতাটি পরীক্ষা করে। উদাহরণস্বরূপ, Compare("0", 0.ToString())মিথ্যা প্রত্যাবর্তন করবে, যেহেতু আর্গুমেন্টগুলি পৃথক স্ট্রিংয়ের উল্লেখ হবে, যার উভয়ই তাদের একমাত্র চরিত্র হিসাবে শূন্য।
সুপারক্যাট

1
সর্বশেষে গৌণ গ্যাচা- আপনি এটি স্ট্রাইকগুলিতে সীমাবদ্ধ করেননি, তাই NullReferenceExceptionঘটতে পারে।
ফ্লাইনে 1179

6

আমার ক্ষেত্রে আমি সমতা অপারেটরের ইউনিট-টেস্ট করতে চেয়েছিলাম। আমার জেনেরিক ধরণটি স্পষ্টভাবে সেট না করেই সাম্যতা অপারেটরের অধীনে কোড কল করা দরকার। পরামর্শ EqualityComparerহিসাবে EqualityComparerবলা Equalsপদ্ধতি হিসাবে সহায়ক ছিল না তবে সমতা অপারেটর নয়।

এখানে কিভাবে আমি একটি নির্মাণের দ্বারা জেনেরিক ধরনের সঙ্গে এই কাজ পেয়েছিলাম করেছি LINQ। এটি ==এবং !=অপারেটরদের জন্য সঠিক কোডকে কল করে :

/// <summary>
/// Gets the result of "a == b"
/// </summary>
public bool GetEqualityOperatorResult<T>(T a, T b)
{
    // declare the parameters
    var paramA = Expression.Parameter(typeof(T), nameof(a));
    var paramB = Expression.Parameter(typeof(T), nameof(b));
    // get equality expression for the parameters
    var body = Expression.Equal(paramA, paramB);
    // compile it
    var invokeEqualityOperator = Expression.Lambda<Func<T, T, bool>>(body, paramA, paramB).Compile();
    // call it
    return invokeEqualityOperator(a, b);
}

/// <summary>
/// Gets the result of "a =! b"
/// </summary>
public bool GetInequalityOperatorResult<T>(T a, T b)
{
    // declare the parameters
    var paramA = Expression.Parameter(typeof(T), nameof(a));
    var paramB = Expression.Parameter(typeof(T), nameof(b));
    // get equality expression for the parameters
    var body = Expression.NotEqual(paramA, paramB);
    // compile it
    var invokeInequalityOperator = Expression.Lambda<Func<T, T, bool>>(body, paramA, paramB).Compile();
    // call it
    return invokeInequalityOperator(a, b);
}

4

এটির জন্য এখানে একটি এমএসডিএন কানেক্ট এন্ট্রি রয়েছে

অ্যালেক্স টার্নারের জবাবটি এর সাথে শুরু হয়:

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


4

আপনি যদি নিশ্চিত করতে চান যে আপনার কাস্টম ধরণের অপারেটররা ডেকেছেন আপনি প্রতিবিম্বের মাধ্যমে এটি করতে পারেন। আপনার জেনেরিক প্যারামিটারটি ব্যবহার করে কেবল টাইপটি পান এবং পছন্দসই অপারেটরের জন্য মেথোডিনফোটি পুনরুদ্ধার করুন (উদাঃ op_Equality, op_Inquality, op_LessThan ...)।

var methodInfo = typeof (T).GetMethod("op_Equality", 
                             BindingFlags.Static | BindingFlags.Public);    

তারপরে মেথিটইনফো-র ইনভোক পদ্ধতিটি ব্যবহার করে অপারেটরটি কার্যকর করুন এবং পরামিতি হিসাবে বস্তুগুলিতে পাস করুন।

var result = (bool) methodInfo.Invoke(null, new object[] { object1, object2});

এটি আপনার ওভারলোডেড অপারেটরকে ডেকে আনবে, জেনেরিক প্যারামিটারে প্রয়োগ করা সীমাবদ্ধতার দ্বারা সংজ্ঞায়িত নয়। ব্যবহারিক নাও হতে পারে তবে জেনেরিক বেস ক্লাস ব্যবহার করে যখন বেশ কয়েকটি পরীক্ষা করে থাকে তখন আপনার অপারেটরদের একক পরীক্ষার কাজে আসে।


3

আমি সর্বশেষে এমএসডিএন দেখে নিম্নলিখিত ফাংশনটি লিখেছিলাম। এটি সহজেই দুটি বস্তুর তুলনা করতে পারে xএবং y:

static bool IsLessThan(T x, T y) 
{
    return ((IComparable)(x)).CompareTo(y) <= 0;
}

4
আপনি আপনার বুলিয়ানগুলি থেকে মুক্তি পেতে পারেন এবং লিখতে পারেনreturn ((IComparable)(x)).CompareTo(y) <= 0;
aloisdg codidact.com এ চলেছে

1

bool Compare(T x, T y) where T : class { return x == y; }

উপরের কাজ করবে কারণ == ব্যবহারকারী-সংজ্ঞায়িত রেফারেন্স ধরণের ক্ষেত্রে যত্ন নেওয়া হয়।
মান ধরণের ক্ষেত্রে, == ওভাররাইড করা যায়। কোন ক্ষেত্রে, "! =" সংজ্ঞায়িত করা উচিত।

আমি মনে করি এটি কারণ হতে পারে, এটি "==" ব্যবহার করে জেনেরিক তুলনা অস্বীকার করে।


2
ধন্যবাদ। আমার বিশ্বাস রেফারেন্স প্রকারগুলি অপারেটরটিকেও ওভাররাইড করতে পারে। তবে ব্যর্থতার কারণ এখন পরিষ্কার।
হোসাম অলি

1
==টোকেন দুটি ভিন্ন অপারেটরের জন্য ব্যবহৃত হয়। প্রদত্ত অপারেন্ড ধরণের জন্য যদি সাম্যতা অপারেটরের একটি সামঞ্জস্যপূর্ণ ওভারলোড উপস্থিত থাকে তবে সেই ওভারলোডটি ব্যবহৃত হবে। অন্যথায় যদি উভয় অপারেন্ডগুলি রেফারেন্স ধরণের হয় যা একে অপরের সাথে সামঞ্জস্যপূর্ণ হয় তবে একটি রেফারেন্স তুলনা ব্যবহার করা হবে। নোট করুন যে Compareসংকলকটির উপরের পদ্ধতিতে প্রথম অর্থটি প্রযোজ্য তা বলতে পারবেন না, তবে দ্বিতীয় অর্থটি প্রযোজ্য তা বলতে পারবেন, সুতরাং টোকনটি সাম্য-চেক অপারেটরটিকে (যেমন এটি টাইপ করা থাকলে ) ওভারলোড করেও== পরে ব্যবহার করবে । TString
সুপারক্যাট

0

.Equals()আমার জন্য কাজ করে যখন TKeyএকটি জেনেরিক প্রকার।

public virtual TOutputDto GetOne(TKey id)
{
    var entity =
        _unitOfWork.BaseRepository
            .FindByCondition(x => 
                !x.IsDelete && 
                x.Id.Equals(id))
            .SingleOrDefault();


    // ...
}

তা- x.Id.Equalsও নয় id.Equals। সম্ভবত, সংকলকটির ধরণ সম্পর্কে কিছু জানে x
হোসাম অলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.