var / নাল আজব আচরণের সাথে স্যুইচ করুন


91

নিম্নলিখিত কোড দেওয়া:

string someString = null;
switch (someString)
{
    case string s:
        Console.WriteLine("string s");
        break;
    case var o:
        Console.WriteLine("var o");
        break;
    default:
        Console.WriteLine("default");
        break;
}

সুইচ স্টেটমেন্টটি মিলছে কেন case var o?

এটি আমার বোঝার সাথে case string sমেলে না s == nullকারণ যখন (কার্যকরভাবে) (null as string) != nullমিথ্যাতে মূল্যায়ন করা হয়। ভিএস কোডে ইন্টেলিজেন্স আমাকে জানায় যে এটিও oএকটি stringভাল। কোন চিন্তা?


সাথে পরিচিত: নাল চেক সহ সি # 7 স্যুইচ কেস


9
নিশ্চিত করা হয়েছে। আমি এই প্রশ্নের ভালবাসি, বিশেষত পর্যবেক্ষণ যে সঙ্গে oকরা হয় string(জেনেরিক্স সঙ্গে নিশ্চিত - অর্থাৎ Foo(o)যেখানে Foo<T>(T template) => typeof(T).Name) - এটি একটি খুব আকর্ষণীয় ক্ষেত্রে দেখা যায় যেখানে string xআচরণ করবে ভিন্নভাবে চেয়ে var xএমনকি যখন x(কম্পাইলার দ্বারা) টাইপ করা হয়string
মার্ক Gravell

7
ডিফল্ট কেসটি ডেড কোড। বিশ্বাস করুন আমাদের সেখানে সতর্কতা জারি করা উচিত। চেক করা হচ্ছে।
জারেডপাড়

13
আমার কাছে এটি বিদ্বেষজনক যে সি # ডিজাইনাররা varএই প্রসঙ্গে একেবারেই অনুমতি দেওয়ার সিদ্ধান্ত নিয়েছেন । এই নিশ্চিতরূপে মনে হয় যে আমি প্রোগ্রামারটিকে "সাফল্যের গর্তে" পরিচালিত করার মতো ভাষা, সি -+ তে খুঁজে পাইনি এমন ধরণের জিনিস বলে মনে হচ্ছে। এখানে, varউভয়ই অস্পষ্ট এবং অকেজো, সি # ডিজাইন এমন জিনিসগুলি এড়াতে সচেষ্ট বলে মনে হয়।
পিটার ডুনিহো

4
@ পিটারডুনিহো আমি অকেজো বলব না; ইনবাউন্ড এক্সপ্রেশনটি switchঅপ্রকাশ্য হতে পারে - বেনামে প্রকারের ইত্যাদি; এবং এটি অস্পষ্ট নয় - সংকলক স্পষ্টভাবে টাইপটি জানে; এটি কেবল বিভ্রান্তিকর (কমপক্ষে আমার কাছে) যে nullনিয়মগুলি এত আলাদা!
মার্ক গ্র্যাভেল

4
@ পিটারডুনিহো মজাদার ঘটনা - আমরা একবার সি # 1.2 স্পেসিফিকেশন থেকে সুনির্দিষ্ট নিয়োগের আনুষ্ঠানিক নিয়মগুলি সন্ধান করেছি এবং বর্ণনামূলক সম্প্রসারণ কোডটির ব্লকের ভিতরে পরিবর্তনশীল ঘোষণা ছিল (এখন এটি এখন); এটি কেবল ২.০-এ বাইরে চলে গেছে , তারপরে যখন ক্যাপচার সমস্যাটি স্পষ্ট ছিল তখন আবার ভিতরে ফিরে।
মার্ক গ্র্যাভেল

উত্তর:


69

একটি সুস্পষ্ট প্রকারের জন্য একটি switchব্যবহার করে একটি প্যাটার্ন মিলের বিবৃতিটি caseজিজ্ঞাসা করছে যে প্রশ্নে মানটি সেই নির্দিষ্ট ধরণের, বা উদ্ভূত প্রকারের। এটি হুবহু সমতুল্যis

switch (someString) {
  case string s:
}
if (someString is string) 

মানটির nullকোনও প্রকার নেই এবং তাই উপরের শর্তগুলির কোনওটিই সন্তুষ্ট করে না। স্থিতিশীল ধরণের someStringকোনও উদাহরণই কার্যকর হয় না।

varটাইপ যদিও প্যাটার্ন ম্যাচিং একটি ওয়াইল্ড কার্ড হিসেবে কাজ করে এবং সহ যেকোন মান ম্যাচ হবে null

এখানে defaultমামলাটি ডেড কোড। এটি case var oকোনও মান, নাল বা নন-নাল সাথে মিলবে। একটি ডিফল্ট ক্ষেত্রে সর্বদা একটি ডিফল্ট ক্ষেত্রে জয়লাভ করে তাই defaultকখনও আঘাত করা হবে না। আপনি যদি আইএলটি দেখেন তবে আপনি দেখতে পাবেন এটি এমনকি নির্গত হয় না।

এক নজরে এটি বিজোড় মনে হতে পারে যে এটি কোনও সতর্কতা ছাড়াই সংকলন করে (অবশ্যই আমাকে ফেলে দিয়েছে)। তবে এটি সি # আচরণের সাথে মিলছে যা 1.0 এ ফিরে যায়। defaultসংকলকটি যখন তুচ্ছভাবে প্রমাণ করতে পারে যে এটি কখনই আঘাত হানে না এমন ক্ষেত্রেও কেসগুলি অনুমতি দেয় । নিম্নলিখিত হিসাবে একটি উদাহরণ হিসাবে বিবেচনা করুন:

bool b = ...;
switch (b) {
  case true: ...
  case false: ...
  default: ...
}

এখানে defaultকখনও আঘাত করা হবে না (এমনকি এর জন্য boolএকটি মানও 1 বা 0 নয়)। তবুও সি # সতর্কতা ছাড়াই 1.0 থেকে এটির অনুমতি দিয়েছে। প্যাটার্ন মিলটি এখানে এই আচরণের সাথে সামঞ্জস্য হয়।


4
যদিও সত্যিকারের সমস্যাটি হ'ল সংকলকটি " সত্যই " varটাইপ হতে হবে stringযখন তা সত্যই নয় (
সত্যটি

@ শ্মুয়েলি varউদাহরণের ধরণটি গণনা করা হয় string
জেয়ার্ডপাড়

4
@ জ্যারেড পার এখানে অন্তর্দৃষ্টিগুলির জন্য ধন্যবাদ; ব্যক্তিগতভাবে আমি সতর্কতাগুলি আরও বেশি নির্গমনকে সমর্থন করব এমনকি এটি এর আগে না করলেও ভাষা দলের প্রতিবন্ধকতাগুলি আমি বুঝতে পারি। আপনি কি কখনও "সব কিছুর মোড সম্পর্কে সাদৃশ্য" (সম্ভবত ডিফল্ট অনুসারে), বনাম "লেগ্যাসি স্টিক মোড" (বৈকল্পিক) বিবেচনা করেছেন? হতে পারেcsc /stiffUpperLip
মার্ক গ্রাভেল

4
@ মার্কগ্রাভেল আমাদের কাছে সতর্কতা তরঙ্গ নামে পরিচিত একটি বৈশিষ্ট্য রয়েছে যার অর্থ নতুন সতর্কতা প্রবর্তন করা আরও সহজ, কম কম্প্যাট ব্রেকি করা। মূলত প্রতিটি সংকলক রিলিজ একটি নতুন তরঙ্গ এবং আপনি / তরঙ্গ: 1, / তরঙ্গ: 2, / তরঙ্গ: সমস্ত মাধ্যমে সতর্কতাগুলিকে বেছে নিতে পারেন।
জারেডপাড়

4
@ জোনাথন ডিকিনসন আমার মনে হয় না যে এটি যা দেখায় তা আপনাকে প্রদর্শন করে। এটি কেবল nullএকটি বৈধ stringরেফারেন্স দেখায় এবং যে কোনও stringরেফারেন্স (সহ null) স্পষ্টভাবে একটি objectরেফারেন্সে (রেফারেন্স-সংরক্ষণ করা) castালাই objectকরা nullযেতে পারে এবং যে কোনও রেফারেন্স সফলভাবে অন্য যে কোনও ধরণের কাছে পরিষ্কার (পরিষ্কার) করা যেতে পারে, এখনও রয়েছে null। সংকলক টাইপ সিস্টেমের ক্ষেত্রে একই জিনিস নয়।
মার্ক গ্র্যাভেল

22

আমি এখানে একাধিক টুইটার মন্তব্য রাখছি - এটি আমার কাছে আসলে নতুন, এবং আমি আশা করছি যে জারেডপার আরও বিস্তৃত উত্তর নিয়ে ঝাঁপিয়ে পড়বে, তবে; আমি এটি বুঝতে পারি হিসাবে সংক্ষিপ্ত সংস্করণ:

case string s:

if(someString is string) { s = (string)someString; ...বা হিসাবে ব্যাখ্যা করা if((s = (someString as string)) != null) { ... }হয় - যার মধ্যে একটির সাথে একটি nullপরীক্ষা জড়িত - যা আপনার ক্ষেত্রে ব্যর্থ হয়েছে; বিপরীতে:

case var o:

সংকলকটি oযেমন stringসহজভাবে সমাধান হয় o = (string)someString; ...- কোনও ধরণের nullপরীক্ষা করা সত্ত্বেও এটি পৃষ্ঠের সাথে একইরকম দেখায়, কেবল সংকলকটি প্রকার সরবরাহ করে providing

অবশেষে:

default:

এখানে পৌঁছানো যায় না , কারণ উপরের কেসটি সমস্ত কিছু ধরে ফেলে। এটি একটি সংকলক বাগ হতে পারে এটি কোনও অ্যাক্র্যাচ্য কোডের সতর্কতা ছাড়েনি।

আমি সম্মত হলাম যে এটি খুব সূক্ষ্ম এবং সংবেদনশীল এবং বিভ্রান্তিকর। তবে দৃশ্যত case var oদৃশ্যটির নাল বংশবিস্তার ( o?.Length ?? 0ইত্যাদি) ব্যবহার রয়েছে। আমি সম্মত হই যে এটি এবং এই যে এটি খুব আলাদাভাবে var oএবং এর মধ্যে খুব আলাদাভাবে কাজ করে string sতবে এটি বর্তমানে কম্পাইলারটি করে।


14

এটি কারণ ডায়নামিক (রান-টাইম) টাইপে case <Type>ম্যাচগুলি স্থির (সংকলন-টাইম) টাইপের নয়। ডায়নামিক টাইপ নেই, তাই এটির সাথে মেলে না । ঠিক পতনnullstringvar

(পোস্ট করা কারণ আমি সংক্ষিপ্ত উত্তর পছন্দ করি।)

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