শর্ট সার্কিটিং অপারেটরগুলি করুন || এবং & অদৃশ্য বুলিয়ানগুলির জন্য বিদ্যমান? রানটাইমবাইন্ডার কখনও কখনও তাই মনে করে


84

আমি শর্তাধীন লজিকাল অপারেটরগুলির উপর সি # ভাষা স্পেসিফিকেশন পড়েছি ||এবং &&এটি সংক্ষিপ্ত-সার্কিট লজিকাল অপারেটর হিসাবেও পরিচিত। আমার কাছে এটি অস্পষ্ট বলে মনে হয়েছিল যে এগুলি নুলযোগ্য বুলিয়ানগুলির জন্য বিদ্যমান ছিল, অর্থাত অপারেন্ড টাইপ Nullable<bool>(এছাড়াও লিখিত bool?), তাই আমি এটি অ-গতিশীল টাইপ করে চেষ্টা করেছি:

bool a = true;
bool? b = null;
bool? xxxx = b || a;  // compile-time error, || can't be applied to these types

এটি প্রশ্নের নিষ্পত্তি বলে মনে হয়েছিল (আমি স্পেসিফিকেশনটি স্পষ্টভাবে বুঝতে পারি না, তবে ভিজ্যুয়াল সি # সংকলকটির বাস্তবায়নটি সঠিক বলে ধরেছিলাম, এখন আমি জানতাম)।

যাইহোক, আমি dynamicপাশাপাশি বাঁধাইয়ের সাথে চেষ্টা করতে চেয়েছিলাম । সুতরাং আমি পরিবর্তে এটি চেষ্টা করেছিলাম:

static class Program
{
  static dynamic A
  {
    get
    {
      Console.WriteLine("'A' evaluated");
      return true;
    }
  }
  static dynamic B
  {
    get
    {
      Console.WriteLine("'B' evaluated");
      return null;
    }
  }

  static void Main()
  {
    dynamic x = A | B;
    Console.WriteLine((object)x);
    dynamic y = A & B;
    Console.WriteLine((object)y);

    dynamic xx = A || B;
    Console.WriteLine((object)xx);
    dynamic yy = A && B;
    Console.WriteLine((object)yy);
  }
}

অবাক করা ফলাফল এটি ব্যতিক্রম ছাড়াই চলে।

ঠিক আছে, xএবং yঅবাক হওয়ার মতো কিছু নেই, তাদের ঘোষণাগুলি উভয় সম্পত্তি পুনরুদ্ধার করতে পরিচালিত করে, এবং ফলস্বরূপ মানগুলি প্রত্যাশার মতো হয়, xহয় trueএবং yহয় null

কিন্তু জন্য মূল্যায়ন xxএর A || Bকোন বাঁধাই-টাইম ব্যতিক্রম নেতৃত্ব, এবং শুধুমাত্র সম্পত্তি Aপড়তে হয়নি B। কেন এমন হয়? আপনি যেমন বলতে পারেন, আমরা Bপাগল বস্তুর মতো ফিরিয়ে দিতে গিটারটি পরিবর্তন করতে পারি, পছন্দ করি "Hello world"এবং xxএখনও trueআবদ্ধ-সমস্যা ছাড়াই মূল্যায়ন করব ...

মূল্যায়ন A && B(জন্য yy) এছাড়াও কোন বাধ্যবাধকতা-সময় ত্রুটি বাড়ে। এবং এখানে উভয় সম্পত্তি অবশ্যই পুনরুদ্ধার করা হয়। এটি রান-টাইম বাইন্ডার দ্বারা অনুমোদিত কেন? যদি প্রত্যাবর্তিত বস্তুটি Bএকটি "খারাপ" অবজেক্টে পরিবর্তিত হয় (যেমন একটিstring ), একটি বাধ্যতামূলক ব্যতিক্রম ঘটে।

এটা কি সঠিক আচরণ?(আপনি কীভাবে অনুমান করতে পারেন?)

আপনি চেষ্টা যদি Bপ্রথম প্রতীক হিসাবে, উভয় B || Aএবং B && A(রানটাইম দপ্তরী ব্যতিক্রম দিতে B | Aএবং B & Aসবকিছু অ শর্ট-সার্কিট অপারেটরদের সঙ্গে স্বাভাবিক কাজ জরিমানা |এবং &)।

(ভিজ্যুয়াল স্টুডিও ২০১৩ এর সি # সংকলক, এবং রানটাইম সংস্করণ। নেট ৪.২.২ দিয়ে চেষ্টা করা হয়েছে)


4
এর Nullable<Boolean>সাথে জড়িত হওয়ার কোনও দৃষ্টান্ত নেই , কেবলমাত্র বক্সযুক্ত বুলিয়ানদের হিসাবে বিবেচনা করা হয় dynamic- এর সাথে আপনার পরীক্ষাটি bool?অপ্রাসঙ্গিক। (অবশ্যই, এটি সম্পূর্ণ উত্তর নয়, কেবল একটির জীবাণু))
জেরোইন মোস্টার্ট

4
A || Bঅর্থে একটি নির্দিষ্ট পরিমাণ তোলে যে আপনি না মূল্যায়ন করতে চান B, যদি না Aমিথ্যা, যা এটি নয়। সুতরাং আপনি কখনই প্রকাশের ধরণটি সত্যই জানেন না। A && Bসংস্করণ আরো বিস্ময়কর - আমি আমি বৈশিষ্ট কি জানতে পারেন দেখতে পাবেন।
জন স্কিটি

4
@JeroenMostert: ওয়েল, যদি না কম্পাইলার সিদ্ধান্ত নিতে যে যদি ধরণ ছিল Aহয় boolএবং এর মান Bহয় null, তারপর bool && bool?অপারেটর জড়িত হতে পারে।
জন স্কিটি

4
মজার বিষয় হচ্ছে, দেখে মনে হচ্ছে এটি কোনও সংকলক বা স্পেক বাগটি প্রকাশ করেছে। &&এটি সমাধান করার মতো আলোচনার জন্য সি # 5.0 স্পেসিফিকেশনটিতে এটি &পরিবর্তে যেমন রয়েছে এবং এতে উভয় অপারেশন রয়েছে এমনটি বিশেষভাবে অন্তর্ভুক্ত রয়েছে bool?- তবে পরবর্তী অংশে এটি উল্লেখযোগ্য ক্ষেত্রে কেস পরিচালনা করবে না। আমি এ সম্পর্কে আরও বিশদে যাওয়ার জন্য এক ধরণের উত্তর যুক্ত করতে পারতাম, তবে এটি সম্পূর্ণরূপে এটি ব্যাখ্যা করবে না।
জন স্কিটে

14
আমি ম্যাডসকে অনুমানের সমস্যাটি সম্পর্কে ইমেল করেছি, আমি এটি কীভাবে পড়ছি তা কেবল একটি সমস্যা কিনা তা দেখার জন্য ...
জন স্কিটি

উত্তর:


67

প্রথমত, নন-ডায়নামিক নুলাবল-বুলের ক্ষেত্রে অনুমানটি পরিষ্কার নয় বলে উল্লেখ করার জন্য ধন্যবাদ। আমি এটি ভবিষ্যতের সংস্করণে ঠিক করব। সংকলকের আচরণ হ'ল উদ্দেশ্যযুক্ত আচরণ; &&এবং ||ননযোগ্য বিলে কাজ করার কথা নয়।

গতিশীল বাইন্ডার এই বিধিনিষেধটি বাস্তবায়িত করে বলে মনে হচ্ছে না। পরিবর্তে, এটি পৃথকভাবে উপাদানগুলির কাজগুলি আবদ্ধ করে: &/ |এবং ?:। সুতরাং এটি প্রথম বিভক্ত হয়ে ওঠে trueবা false(যা বুলিয়ান মান এবং এইভাবে প্রথম অপারেন্ড হিসাবে অনুমোদিত ?:) এর মধ্য দিয়ে গোলমাল করতে সক্ষম হয় , তবে আপনি যদি nullপ্রথম অপারেন্ড হিসাবে দেন (যেমন আপনি চেষ্টা করেন তবেB && A উপরের উদাহরণে থাকেন), আপনি করবেন একটি রানটাইম বাঁধাই ব্যতিক্রম পান।

আপনি যদি এটির বিষয়ে চিন্তা করেন তবে দেখতে পাবেন যে আমরা কেন একটি বড় গতিশীল অপারেশন না হয়ে এইভাবে গতিশীল &&এবং ||এইভাবে প্রয়োগ করেছি: গতিশীল ক্রিয়াকলাপগুলি তাদের অপারেশনগুলি মূল্যায়ন করার পরে রানটাইম এ সীমাবদ্ধ থাকে , যাতে বাধ্যতামূলক ফলাফলের রানটাইম ধরণের ভিত্তিতে তৈরি করা যায় যারা মূল্যায়ন। কিন্তু এই ধরনের উত্সাহী মূল্যায়ন শর্ট সার্কিটিং অপারেটরদের উদ্দেশ্যকে পরাস্ত করে! সুতরাং পরিবর্তে, গতিশীল জন্য উত্পন্ন কোড &&এবং ||মূল্যায়ন টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো করে

  • বাম অপারেন্ড মূল্যায়ন করুন (আসুন ফলাফলটি কল করুন x)
  • এটিকে boolঅন্তর্নিহিত রূপান্তর, trueবা falseঅপারেটরগুলির মাধ্যমে পরিণত করার চেষ্টা করুন (অক্ষম হলে ব্যর্থ হন)
  • xকোনও ?:অপারেশনে শর্ত হিসাবে ব্যবহার করুন
  • সত্য শাখায়, xফলস্বরূপ ব্যবহার করুন
  • মিথ্যা শাখায়, এখন দ্বিতীয় অপারেন্ডকে মূল্যায়ন করুন (আসুন ফলাফলটি কল করুন y)
  • রানটাইম ধরণের প্রকারের ভিত্তিতে &বা |অপারেটরটিকে আবদ্ধ করার চেষ্টা করুন xএবং y(অক্ষম হলে ব্যর্থ হন)
  • নির্বাচিত অপারেটর প্রয়োগ করুন

এই আচরণ operands নির্দিষ্ট "অবৈধ" সমন্বয় মাধ্যমে করতে দেয়: ?:অপারেটর সফলভাবে একটি হিসাবে প্রথম প্রতীক একইরূপে অ nullable বুলিয়ান, &বা |অপারেটর সফলভাবে একটি যেমন একইরূপে nullable বুলিয়ান এবং দুটি চেক করার জন্য যে তারা একমত তুল্য কখনো ।

সুতরাং এটি যে গতিশীল নয় && এবং || nlalables উপর কাজ। স্ট্যাটিক কেসের তুলনায় এগুলি কেবল এমনভাবে প্রয়োগ করা হবে যা কিছুটা খুব বিনীত হয়। এটি সম্ভবত একটি ত্রুটি হিসাবে বিবেচনা করা উচিত, তবে আমরা এটি কখনই ঠিক করব না, কারণ এটি একটি ব্রেকিং পরিবর্তন হবে। এছাড়াও আচরণ কঠোর করতে খুব কমই কাউকে সহায়তা করবে।

আশা করি এটি কী ঘটে এবং কেন তা ব্যাখ্যা করে! এটি একটি উদ্বেগজনক অঞ্চল এবং আমি প্রায়শই নিজেকে গতিশীল করার সময় আমরা যে সিদ্ধান্ত নিয়েছিলাম সেগুলির পরিণতিতে নিজেকে বিভ্রান্ত করতে দেখি। এই প্রশ্নটি সুস্বাদু ছিল - এটি আনার জন্য ধন্যবাদ!

ম্যাডস


আমি দেখতে পাচ্ছি যে এই সংক্ষিপ্ত সার্কিটিং অপারেটরগুলি বিশেষ, কারণ গতিশীল বাঁধাইয়ের সাথে আমাদের যেভাবে সংক্ষিপ্ত-সার্কিট হয় সেখানে দ্বিতীয় অপারেন্ডের ধরণটি সত্যই আমাদের জানার অনুমতি নেই। সম্ভবত চশমা উল্লেখ করা উচিত? অবশ্যই, সাল থেকে ভিতরে সবকিছু dynamicboxed, তখন আমরা এর মধ্যে পার্থক্য বলতে পারে না bool?যা HasValue, এবং একটি "সরল" bool
জেপ্পে স্টিগ নীলসন

6

এটা কি সঠিক আচরণ?

হ্যাঁ, আমি নিশ্চিত এটি।

আপনি কিভাবে অনুমান থেকে অনুমান করতে পারেন?

সি # স্পেসিফিকেশন সংস্করণ 5.0 এর 7.12 সেকশনে শর্তাধীন অপারেটরগুলি &&এবং ||গতিশীল বাঁধাইয়ের সাথে কীভাবে সম্পর্কিত তার তথ্য রয়েছে । সম্পর্কিত বিভাগ:

যদি শর্তাধীন লজিকাল অপারেটরের অপারেন্ডে সংকলন-টাইপ টাইপ গতিশীল থাকে, তবে এক্সপ্রেশনটি গতিশীলভাবে আবদ্ধ হয় (§7.2.2)। এক্ষেত্রে সংকলন-টাইপের ধরণের অভিব্যক্তিটি গতিশীল এবং নীচে বর্ণিত রেজোলিউশনটি সেই সংকলন-টাইপ ধরণের গতিশীল রয়েছে এমন অপারেশনগুলির রান-টাইম ধরণের সাহায্যে রান-টাইমে সংঘটিত হবে

আমি মনে করি এটিই মূল পয়েন্ট যা আপনার প্রশ্নের উত্তর দেয়। রান-টাইমে ঘটে যাওয়া রেজোলিউশনটি কী? বিভাগ 7.12.2, ব্যবহারকারী-সংজ্ঞায়িত শর্তাধীন লজিকাল অপারেটরগুলি ব্যাখ্যা করে:

  • অপারেশন এক্স ও অ্যান্ড ওয়াই টি টিফালস (এক্স) হিসাবে মূল্যায়ন করা হয়? x: টি। ও (এক্স, ওয়াই), যেখানে টি.ফালস (এক্স) টি অপারেটারের মিথ্যা হিসাবে টি তে ঘোষিত, এবং টি। এবং (x, y) নির্বাচিত অপারেটর এবং একটি আহবান &
  • অপারেশন এক্স || y কে T.true (x) হিসাবে মূল্যায়ন করা হয়? x: T. | (x, y), যেখানে T.true (x) অপারেটারের সত্য হিসাবে টি তে ঘোষিত, এবং টি। | (x, y) নির্বাচিত অপারেটরের অনুরোধ।

উভয় ক্ষেত্রেই প্রথম অপারেন্ড এক্স falseবা trueঅপারেটরগুলি ব্যবহার করে একটি বিলে রূপান্তরিত হবে । তারপরে উপযুক্ত লজিকাল অপারেটরকে ডাকা হয়। এটি মাথায় রেখে, আপনার বাকী প্রশ্নের উত্তর দেওয়ার জন্য আমাদের কাছে পর্যাপ্ত তথ্য রয়েছে।

তবে এক্স এর xx এর জন্য মূল্যায়ন খ কোনও বাধ্যবাধকতা-সময় ব্যতিক্রম না করে এবং কেবল সম্পত্তি এ পড়েছিল, বি নয়, কেন এটি ঘটে?

জন্য ||অপারেটর, আমরা এটা অনুসরণ করে জানি true(A) ? A : |(A, B)। আমরা শর্ট সার্কিট, সুতরাং আমরা একটি বাধ্যবাধকতা সময় ব্যতিক্রম পাবেন না। এমনকি যদি Aছিল false, আমরা চাই এখনও নয় রানটাইম বাঁধাই ব্যতিক্রম, কারণ নির্দিষ্ট রেজল্যুশন ধাপের পেতে। যদি Aহয় falseতবে আমরা |অপারেটরটি করি, যা ধারা 7.11.4 অনুযায়ী সাফল্যের সাথে নাল মানগুলি পরিচালনা করতে পারে।

A&& B (yy এর জন্য) মূল্যায়ন করাও বাধ্যবাধকতা-সময় ত্রুটির দিকে পরিচালিত করে না। এবং এখানে উভয় সম্পত্তি অবশ্যই পুনরুদ্ধার করা হয়। এটি রান-টাইম বাইন্ডার দ্বারা অনুমোদিত কেন? যদি বি থেকে প্রত্যাবর্তিত অবজেক্টটি একটি "খারাপ" অবজেক্টে (স্ট্রিংয়ের মতো) পরিবর্তিত হয়, তবে একটি বাঁধাই ব্যতিক্রম ঘটে।

একই কারণে, এটিও কাজ করে। &&হিসাবে মূল্যায়ন করা হয় false(x) ? x : &(x, y)Aসফলভাবে একটিতে রূপান্তরিত হতে পারে bool, সুতরাং সেখানে কোনও সমস্যা নেই। যেহেতু Bনাল, &অপারেটরটিকে পরামিতিগুলি boolগ্রহণ করে এমন এক থেকে নেওয়া হয় (বিভাগ 7.3.7) bool?এবং তাই রানটাইম ব্যতিক্রম নেই।

উভয় শর্তসাপেক্ষ অপারেটরদের জন্য, যদি Bএকটি বুল (বা নাল ডায়নামিক) ব্যতীত অন্য কিছু হয়, রানটাইম বাঁধাই ব্যর্থ হয় কারণ এটি পরামিতি হিসাবে একটি বল এবং একটি নন-বুল লাগে এমন একটি ওভারলোড খুঁজে পায় না। যাইহোক, এই শুধুমাত্র যদি ঘটে A(অপারেটর প্রথম শর্তসাপেক্ষ সন্তুষ্ট করতে ব্যর্থ trueজন্য ||, falseজন্য &&)। এটি হওয়ার কারণ হ'ল ডায়নামিক বাইন্ডিং বেশ অলস। এটি Aমিথ্যা না হলে লজিকাল অপারেটরটিকে আবদ্ধ করার চেষ্টা করবে না এবং লজিকাল অপারেটরকে মূল্যায়নের জন্য এই পথে যেতে হবে। একবার Aঅপারেটরের জন্য প্রথম শর্তটি পূরণ করতে ব্যর্থ হলে এটি বাধ্যতামূলক ব্যতিক্রমের সাথে ব্যর্থ হবে।

আপনি যদি প্রথম অপারেন্ড হিসাবে বি চেষ্টা করেন তবে উভয় বি || A এবং B&&A রানটাইম বাইন্ডার ব্যতিক্রম দেয়।

আশা করি, এতক্ষণে আপনি ইতিমধ্যে জানেন যে কেন এটি ঘটে (বা আমি একটি খারাপ কাজ ব্যাখ্যা করেছিলাম)। এই শর্তসাপেক্ষ অপারেটরের সমাধানের প্রথম পদক্ষেপটি হ'ল লজিক্যাল অপারেশন পরিচালনা করার আগে প্রথম অপারেন্ড গ্রহণ করা Bএবং বুল রূপান্তর অপারেটরগুলির একটি ( false(B)বা true(B)) ব্যবহার করা use অবশ্যই, Bসত্তা nullহয় trueবা হয় রূপান্তর করা যায় না false, এবং তাই রানটাইম বাঁধাই ব্যতিক্রম ঘটে।


অবাক হওয়ার কিছু নেই যে dynamicবাইন্ডিংটি রান-টাইমে ঘটনাগুলির প্রকৃত প্রকারগুলি ব্যবহার করে ঘটে, সংকলন-সময়ের ধরণের (আপনার প্রথম উদ্ধৃতি) নয়। কারণ কোনো প্রকার এখানে overloads তোমার দ্বিতীয় উদ্ধৃতি অপ্রাসঙ্গিক operator trueএবং operator false। একটি explicit operatorফেরার boolচেয়ে অন্য কিছু operator trueএবং false। এটা কোনো উপায় পারবেন যে বৈশিষ্ট পড়া কঠিন A && Bএছাড়াও যার ফলে ছাড়াই (আমার উদাহরণে) a && bযেখানে aএবং bস্ট্যাটিক্যালি টাইপ করা হয় nullable Booleans, অর্থাত্ bool? aএবং bool? bকম্পাইল-সময়ে বাঁধাই সঙ্গে। তবুও এটি অনুমোদিত নয়।
জেপ্পে স্টিগ নীলসেন

-1

নুলযোগ্য টাইপ শর্তাধীন লজিকাল অপারেটরগুলি সংজ্ঞায়িত করে না || এবং &&. আমি আপনাকে কোড অনুসরণ করার পরামর্শ দিচ্ছি:

bool a = true;
bool? b = null;

bool? xxxxOR = (b.HasValue == true) ? (b.Value || a) : a;
bool? xxxxAND = (b.HasValue == true) ? (b.Value && a) : false;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.