ডাবল জন্য "==" অপারেটরের সংজ্ঞা


126

কোনও কারণে আমি ক্লাসের জন্য .NET ফ্রেমওয়ার্ক উত্সে স্নেহ করছিলাম Doubleএবং জানতে পেরেছিলাম যে এর ঘোষণাটি ==হ'ল:

public static bool operator ==(Double left, Double right) {
    return left == right;
}

একই যুক্তি প্রতিটি অপারেটরের ক্ষেত্রে প্রযোজ্য ।


  • এমন সংজ্ঞার মূল বক্তব্য কী?
  • এটা কিভাবে কাজ করে?
  • কেন এটি অসীম পুনরাবৃত্তি তৈরি করে না?

17
আমি একটি অন্তহীন পুনরাবৃত্তি আশা করি।
হিমব্রুমবিয়ার

5
আমি নিশ্চিত যে এটি কোথাও দ্বিগুণ সাথে তুলনার জন্য ব্যবহৃত হয় না, পরিবর্তে ceqআইএল জারি করা হয়। কিছু ডকুমেন্টেশনের উদ্দেশ্য পূরণ করার জন্য এটি এখানে রয়েছে, যদিও উত্সটি খুঁজে পাচ্ছে না।
হাবিব

2
সম্ভবত এই অপারেটর প্রতিচ্ছবি মাধ্যমে প্রাপ্ত করা যেতে পারে।
ড্যামিয়েন_আ_বিশ্বাসীরা

3
এটিকে কখনই বলা হবে না, সংকলকটিতে সমতা যুক্তি বেকড রয়েছে (সিএইচকি অপকোড) দেখুন কখন ডাবল এর == অপারেটরটি
অ্যালেক্স কে।

1
@ জোহরপিল্ড শূন্যের সাথে একটি ডাবলকে ভাগ করা বৈধ এবং এটি ইতিবাচক বা নেতিবাচক অসীমের ফলাফল করবে।
ম্যাগনাস

উত্তর:


62

বাস্তবে, সংকলক ==অপারেটরটিকে ceqআইএল কোডে পরিণত করবে এবং আপনি যে অপারেটরের উল্লেখ করেছেন তাকে কল করা হবে না।

উত্স কোডে অপারেটরের কারণ সম্ভবত এটি সি # ব্যতীত অন্য ভাষাগুলি থেকে CEQকল করা যেতে পারে যা এটি সরাসরি কোনও কলে অনুবাদ করে না (বা প্রতিবিম্বের মাধ্যমে)। অপারেটরের মধ্যে কোডটি একটিতে সংকলিত হবেCEQ , সুতরাং অসীম পুনরাবৃত্তি নেই।

প্রকৃতপক্ষে, আপনি যদি প্রতিবিম্বের মাধ্যমে অপারেটরকে কল করেন তবে আপনি দেখতে পাবেন যে অপারেটরটি ডাকা হয় (কোনও CEQনির্দেশের চেয়ে নয় ), এবং স্পষ্টতই অসীম পুনরাবৃত্তি হয় না (যেহেতু প্রোগ্রামটি প্রত্যাশা অনুযায়ী শেষ হয়):

double d1 = 1.1;
double d2 = 2.2;

MethodInfo mi = typeof(Double).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public );

bool b = (bool)(mi.Invoke(null, new object[] {d1,d2}));

রেজাল্টিং আইএল (লিনকপ্যাড 4 সংকলিত):

IL_0000:  nop         
IL_0001:  ldc.r8      9A 99 99 99 99 99 F1 3F 
IL_000A:  stloc.0     // d1
IL_000B:  ldc.r8      9A 99 99 99 99 99 01 40 
IL_0014:  stloc.1     // d2
IL_0015:  ldtoken     System.Double
IL_001A:  call        System.Type.GetTypeFromHandle
IL_001F:  ldstr       "op_Equality"
IL_0024:  ldc.i4.s    18 
IL_0026:  call        System.Type.GetMethod
IL_002B:  stloc.2     // mi
IL_002C:  ldloc.2     // mi
IL_002D:  ldnull      
IL_002E:  ldc.i4.2    
IL_002F:  newarr      System.Object
IL_0034:  stloc.s     04 // CS$0$0000
IL_0036:  ldloc.s     04 // CS$0$0000
IL_0038:  ldc.i4.0    
IL_0039:  ldloc.0     // d1
IL_003A:  box         System.Double
IL_003F:  stelem.ref  
IL_0040:  ldloc.s     04 // CS$0$0000
IL_0042:  ldc.i4.1    
IL_0043:  ldloc.1     // d2
IL_0044:  box         System.Double
IL_0049:  stelem.ref  
IL_004A:  ldloc.s     04 // CS$0$0000
IL_004C:  callvirt    System.Reflection.MethodBase.Invoke
IL_0051:  unbox.any   System.Boolean
IL_0056:  stloc.3     // b
IL_0057:  ret 

উত্সাহের ব্যাপার হল - একই অপারেটার অবিচ্ছেদ্য ধরনের জন্য উপস্থিত না থাকার (হয় রেফারেন্স উৎস প্রতিফলন অথবা এর মাধ্যমে), শুধুমাত্র Single, Double, Decimal, String, এবং DateTime, আমার তত্ত্ব disproves যা তারা অন্য ভাষা থেকে বলা হবে বিদ্যমান। স্পষ্টতই আপনি এই অপারেটরগুলি ব্যতীত অন্য ভাষায় দুটি পূর্ণসংখ্যার সমান করতে পারেন, সুতরাং আমরা "কেন তাদের উপস্থিতি" এই প্রশ্নে ফিরে এসেছি double?


12
এটির সাথে আমি কেবল দেখতে পাচ্ছি সমস্যাটি হ'ল সি # ভাষার স্পেসিফিকেশন বলে যে ওভারলোডেড অপারেটরগুলি বিল্ট-ইন অপারেটরগুলির চেয়ে বেশি প্রাধান্য দেয়। সুতরাং অবশ্যই, একটি উপযুক্ত সি # সংকলকটি দেখতে পাবে যে এখানে একটি ওভারলোডেড অপারেটর উপলব্ধ রয়েছে এবং অসীম পুনরাবৃত্তি উত্পন্ন করে। হুম। সমস্যাগ্রস্থ।
ড্যামিয়েন_এ_বিশ্বাসীরা

5
এই প্রশ্নের উত্তর দেয় না, ইমো। এটি কেবল কোডটি অনুবাদ করে তবে কেন নয় তা ব্যাখ্যা করে। বিভাগের 7.3.4 অনুযায়ী বাইনারি অপারেটর ওভারলোড রেজোলিউশন সি # ভাষার স্পেসিফিকেশনটির সাথে আমিও অসীম পুনরাবৃত্তি আশা করব। আমি ধরে নেব যে রেফারেন্স উত্স (রেফারেন্সসোর্স.মাইক্রোসফট /#mscorlib/ system/… ) এখানে সত্যিই প্রয়োগ হয় না।
ডার্ক ভোলমার

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

1
@ ড্যামিয়েন_সে_ অবিশ্বাসীরা এজন্যই আমি মনে করি এটি হয় একটি ব্যতিক্রম বা "বিল্ট-ইন" অপারেটরগুলির আলাদা ব্যাখ্যা।
ডি স্ট্যানলি

1
যেহেতু @ জোন স্কিটি এখনও এর জবাব দেয়নি বা মন্তব্য করেছে না, আমি সন্দেহ করি এটি একটি বাগ (অর্থাত্ স্পেসের লঙ্ঘন)।
দ্য ব্লাস্টঅন

37

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

স্ট্যান্ডার্ড সি # তে, আপনি যে কোডটি দেখছেন সেটির ফলে অপারেটর ওভারলোড রেজোলিউশনটি যেভাবে কাজ করে তার ফলস্বরূপ স্ট্যাক ওভারফ্লো হবে। তবে কোডটি আসলে স্ট্যান্ডার্ড সি # তে নেই - এটি মূলত সি # সংকলকের অননুমোদিত বৈশিষ্ট্যগুলি ব্যবহার করে। অপারেটরকে কল করার পরিবর্তে, এই কোডটি প্রকাশ করে:

ldarg.0
ldarg.1
ceq
ret

এটাই :) 100% সমতুল্য সি # কোড নেই - এটি নিজের ধরণের মাধ্যমে সি # তে সহজভাবে সম্ভব নয় ।

তারপরেও, সি # কোডটি সংকলনের সময় প্রকৃত অপারেটর ব্যবহার করা হয় না - সংকলক এই ক্ষেত্রে যেমন একচেটিয়া অপ্টিমাইজেশন করে, যেখানে এটি op_Equalityকলটি সহজ সরল করে প্রতিস্থাপন করে ceq। আবার, আপনি DoubleExএটি নিজের স্ট্রাক্টে প্রতিলিপি করতে পারবেন না - এটি সংকলক যাদু।

এটি নেট। নেট-এ কোনও অনন্য পরিস্থিতি নয় - প্রচুর কোড যা বৈধ নয়, মান সি #। কারণগুলি হ'ল (ক) সংকলক হ্যাক এবং (খ) একটি ভিন্ন ভাষা, বিজোড় (সি) রানটাইম হ্যাক (আমি আপনার দিকে তাকাচ্ছি Nullable!)।

যেহেতু রোজলিন সি # সংকলক ওপেন উত্স, তাই আপনাকে ওভারলোড রেজোলিউশনের সিদ্ধান্ত নিয়েছে এমন স্থানে আমি আপনাকে সত্যিই নির্দেশ করতে পারি:

সমস্ত বাইনারি অপারেটরগুলি সমাধান করার জায়গা

অভ্যন্তরীণ অপারেটরদের জন্য "শর্টকাট"

আপনি যখন শর্টকাটগুলি দেখুন, আপনি দেখবেন যে দ্বিগুণ এবং দ্বিগুণ ফলাফলের মধ্যে অন্তর্নিহিত ডাবল অপারেটরের ক্ষেত্রে কখনও কখনও প্রকৃত ==অপারেটরটিতে টাইপ অনুযায়ী সংজ্ঞায়িত হয় না। .NET টাইপ সিস্টেমে ভান করতে Doubleহবে যে এটি অন্যর মতো টাইপ, তবে সি # হয় না - doubleএটি সি # তে একটি আদিম।


1
নিশ্চিত নই যে আমি সম্মত হই যে রেফারেন্স উত্সের কোডটি কেবল "বিপরীত ইঞ্জিনিয়ারড"। কোডটিতে সংকলক নির্দেশাবলী ( #ifগুলি) এবং অন্যান্য নিদর্শন রয়েছে যা সংকলিত কোডে উপস্থিত থাকবে না। এছাড়াও যদি এটির জন্য বিপরীত ইঞ্জিনিয়ারিং করা হয় doubleতবে কেন এটির জন্য বিযুক্ত ইঞ্জিনিয়ারিং করা হয়নি intবা long? আমি মনে করি উত্স কোডের কোনও কারণ আছে তবে আমি বিশ্বাস করি যে ==অপারেটরের অভ্যন্তরের ব্যবহার এমন একটি সংকলিত হয় CEQযা পুনরাবৃত্তি রোধ করে। যেহেতু অপারেটর সেই ধরণের জন্য "পূর্বনির্ধারিত" অপারেটর (এবং ওভাররাইড করা যায় না) ওভারলোডের বিধি প্রযোজ্য না।
ডি স্ট্যানলে

@ ডিস্টানলি আমি বোঝাতে চাইনি যে সমস্ত কোড বিপরীত ইঞ্জিনিয়ারড। এবং আবারও, doubleছাত্রলীগের অংশ নয় - এটি একটি পৃথক লাইব্রেরিতে রয়েছে, যা কেবল # সি নির্দিষ্টকরণের অন্তর্ভুক্ত হতে পারে। হ্যাঁ, এটি ==একটিতে সংকলিত হয় ceq, তবে এর অর্থ এটি একটি সংকলক হ্যাক যা আপনি নিজের কোডে প্রতিলিপি করতে পারবেন না, এবং এমন কিছু যা সি # স্পেসিফিকেশনের অংশ নয় ( স্ট্রাক্টের float64ক্ষেত্রের মতো Double)। এটি সি # এর চুক্তিভিত্তিক অংশ নয়, সুতরাং এটি সি # সংকলক দিয়ে সংকলিত হলেও, এটি বৈধ সি # এর মতো চিকিত্সা করার সামান্য বিষয়।
লুয়ান

@ ডিটেইলি আমি বাস্তব কাঠামোটি কীভাবে সংগঠিত হয়েছে তা খুঁজে পাইনি, তবে। নেট 2.0 এর রেফারেন্স প্রয়োগে, সমস্ত জটিল অংশগুলি কেবলমাত্র সংকলক অভ্যন্তরীণ, সি ++ এ প্রয়োগ করা হয়েছে। অবশ্যই অনেকগুলি নেট নেট কোড রয়েছে, অবশ্যই, তবে "টু ডাবলসের তুলনা করা" এর মতো জিনিসগুলি খাঁটি। নেট এ আসলেই ভাল কাজ করবে না; ভাসমান পয়েন্ট সংখ্যাগুলি ছাত্রলীগের অন্তর্ভুক্ত না হওয়ার অন্যতম কারণ। এটি বলেছিল যে কোডটি (অ-মানক) সি # তেও প্রয়োগ করা হয়েছে, সম্ভবত আপনি আগে উল্লিখিত কারণটির জন্যই - অন্যান্য। নেট সংকলকরা এই জাতীয়গুলিকে আসল .NET প্রকার হিসাবে বিবেচনা করতে পারে তা নিশ্চিত করার জন্য।
লুয়ান

@ ডিস্টানলি তবে ঠিক আছে, পয়েন্টটি নেওয়া হয়েছে। আমি "বিপরীত ইঞ্জিনিয়ারড" রেফারেন্সটি সরিয়ে দিয়েছি এবং উত্তরটি কেবলমাত্র সি # এর পরিবর্তে "স্ট্যান্ডার্ড সি #" উল্লেখ করার জন্য সন্ধান করেছি word আর চিকিত্সা না doubleমতো একই ভাবে intএবং long- intএবং longআদিম ধরনের যে সব .NET ভাষায় সমর্থন করতে হবে। float, decimalএবং doubleনা।
লুয়ান

12

আদিম ধরণের উত্স বিভ্রান্তিকর হতে পারে। আপনি Doubleকাঠামোর প্রথম লাইনটি দেখেছেন ?

সাধারণত আপনি এটির মতো পুনরাবৃত্ত স্ট্রাক্ট সংজ্ঞায়িত করতে পারবেন না:

public struct Double : IComparable, IFormattable, IConvertible
        , IComparable<Double>, IEquatable<Double>
{
    internal double m_value; // Self-recursion with endless loop?
    // ...
}

সিআইএল-এও আদিম ধরণের তাদের আদি সমর্থন রয়েছে। সাধারণত এগুলি অবজেক্ট-ওরিয়েন্টড প্রকারের মতো আচরণ করা হয় না। যদি একটি float64সিআইএল-এর মতো ব্যবহার করা হয় তবে একটি ডাবল কেবল একটি -৪-বিটের মান । যাইহোক, যদি এটি সাধারণ .NET টাইপ হিসাবে পরিচালনা করা হয় তবে এটিতে একটি আসল মান থাকে এবং এতে অন্য যে কোনও ধরণের মতো পদ্ধতি রয়েছে।

সুতরাং আপনি এখানে যা দেখছেন তা অপারেটরদের একই অবস্থা। সাধারণত আপনি ডাবল টাইপ টাইপ সরাসরি ব্যবহার করেন, এটি কখনও কল করা হবে না। বিটিডাব্লু, এর উত্সটি সিআইএল-তে এর মত দেখাচ্ছে:

.method public hidebysig specialname static bool op_Equality(float64 left, float64 right) cil managed
{
    .custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor()
    .custom instance void __DynamicallyInvokableAttribute::.ctor()
    .maxstack 8
    L_0000: ldarg.0
    L_0001: ldarg.1
    L_0002: ceq
    L_0004: ret
}

যেমন আপনি দেখতে পাচ্ছেন, কোনও অন্তহীন লুপ নেই (কলটি ceqকল করার পরিবর্তে উপকরণটি ব্যবহৃত হয় System.Double::op_Equality)। সুতরাং যখন কোনও দ্বিগুণকে কোনও বস্তুর মতো আচরণ করা হয়, অপারেটর পদ্ধতিটি কল করা হবে, যা শেষ পর্যন্ত এটি float64সিআইএল স্তরের আদিম ধরণের হিসাবে পরিচালনা করবে ।


1
যারা এই পোস্টের প্রথম অংশটি বুঝতে পারেন না (তারা সাধারণত নিজের মানের ধরণের লেখেন না কারণ), কোডটি চেষ্টা করে দেখুন public struct MyNumber { internal MyNumber m_value; }। এটি অবশ্যই সংকলিত হতে পারে না। ত্রুটিটি ত্রুটিটি CS0523: স্ট্রাক্ট সদস্য 'MyNumber.m_value' টাইপের 'মাই নাম্বার' স্ট্রাক্ট লেআউটে একটি চক্রের কারণ ঘটায়
জেপ্পে স্টিগ নীলসেন

8

আমি জাস্টডেকম্পাইল সহ সিআইএল-এর দিকে একবার নজর রেখেছি। অভ্যন্তরটি ==সিআইএল সিএইচএইচপি কোডটিতে অনুবাদ হয়ে যায় । অন্য কথায়, এটি আদিম সিএলআর সমতা।

আমি দ্বিগুণ মানগুলির তুলনা করার সময় সি # সংকলকটি রেফারেন্স দেয় ceqবা ==অপারেটরটি কিনা তা জানতে আগ্রহী ছিলাম । তুচ্ছ উদাহরণে আমি (নীচে) নিয়ে এসেছি, এটি ব্যবহৃত হয়েছিল ceq

এই প্রোগ্রাম:

void Main()
{
    double x = 1;
    double y = 2;

    if (x == y)
        Console.WriteLine("Something bad happened!");
    else
        Console.WriteLine("All is right with the world");
}

নিম্নলিখিত সিআইএল উত্পন্ন করে (লেবেল সহ বিবৃতিটি নোট করুন IL_0017):

IL_0000:  nop
IL_0001:  ldc.r8      00 00 00 00 00 00 F0 3F
IL_000A:  stloc.0     // x
IL_000B:  ldc.r8      00 00 00 00 00 00 00 40
IL_0014:  stloc.1     // y
IL_0015:  ldloc.0     // x
IL_0016:  ldloc.1     // y
IL_0017:  ceq
IL_0019:  stloc.2
IL_001A:  ldloc.2
IL_001B:  brfalse.s   IL_002A
IL_001D:  ldstr       "Something bad happened!"
IL_0022:  call        System.Console.WriteLine
IL_0027:  nop
IL_0028:  br.s        IL_0035
IL_002A:  ldstr       "All is right with the world"
IL_002F:  call        System.Console.WriteLine
IL_0034:  nop
IL_0035:  ret

-2

যেমন সিস্টেমের জন্য মাইক্রোসফ্ট ডকুমেন্টেশনে ইঙ্গিত করা হয়েছে।রুনটাইম.ভিশন নেমস্পেস: এই নেমস্পেসে পাওয়া প্রকারগুলি .NET ফ্রেমওয়ার্কের মধ্যে ব্যবহারের জন্য এবং ব্যবহারকারী অ্যাপ্লিকেশনগুলির জন্য নয় System সিস্টেম.রুনটাইম.ভির্জনিং নেমস্পেসে উন্নত প্রকার রয়েছে যা সংস্করণটিকে সমর্থন করে .NET ফ্রেমওয়ার্কের পাশাপাশি বাস্তবায়ন।


এর সাথে কী System.Runtime.Versioningকরতে হবে System.Double?
কোপাকিলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.