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




.net language-lawyer (4)

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

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

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

সিআইএল-তেও আদিম ধরণের তাদের আদি সমর্থন রয়েছে। সাধারণত এগুলি বস্তু-কেন্দ্রিক প্রকারের মতো আচরণ করা হয় না। একটি ডাবল কেবল একটি float64 বিটের মান হিসাবে ব্যবহৃত হয় যদি এটি float64 64 হিসাবে ব্যবহৃত হয়। যাইহোক, যদি এটি সাধারণ .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
}

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

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

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

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

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

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

আমি দেখতে আগ্রহী ছিলাম যে সি # সংকলক দুটি দ্বৈত মানের তুলনা করার সময় ceq বা == অপারেটরটি রেফারেন্স করবে ceq । তুচ্ছ উদাহরণে আমি (নীচে) নিয়ে এসেছি, এটি 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

বাস্তবে, ceq == অপারেটরটিকে একটি ceq আইএল 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 , যা আমার তত্ত্বকে অস্বীকার করে যে তারা অন্য ভাষা থেকে ডেকে ডেকেছে। স্পষ্টতই আপনি এই অপারেটরগুলি ব্যতীত অন্য ভাষায় দুটি পূর্ণসংখ্যার সমান করতে পারেন, তাই আমরা "এগুলি double কেন বিদ্যমান" এই প্রশ্নে ফিরে এসেছি?


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







language-lawyer