সি # তে, যখন আপনি নাল বস্তুর উপর কোনও এক্সটেনশন পদ্ধতি কল করবেন তখন কী হবে?


328

পদ্ধতিটি কি নাল মান সহ কল ​​হয় বা এটি একটি নাল রেফারেন্স ব্যতিক্রম দেয়?

MyObject myObject = null;
myObject.MyExtensionMethod(); // <-- is this a null reference exception?

যদি এটি হয় তবে শূন্যতার জন্য আমার 'এই' প্যারামিটারটি কখনই পরীক্ষা করতে হবে না?


অবশ্যই না করে আপনি এএসপি.নেট এমভিসি এর সাথে কাজ করছেন যা এই ত্রুটিটি ফেলে দেবে Cannot perform runtime binding on a null reference
মিচিফ

উত্তর:


386

এটি সূক্ষ্মভাবে কাজ করবে (ব্যতিক্রম নয়)। এক্সটেনশন পদ্ধতিগুলি ভার্চুয়াল কলগুলি ব্যবহার করে না (যেমন এটি "কল" ইল নির্দেশনা ব্যবহার করে, "কলভার্ট" নয়) সুতরাং আপনি এক্সটেনশন পদ্ধতিতে নিজেকে না লিখলে কোনও নাল চেক নেই। এটি আসলে কয়েকটি ক্ষেত্রে কার্যকর:

public static bool IsNullOrEmpty(this string value)
{
    return string.IsNullOrEmpty(value);
}
public static void ThrowIfNull<T>(this T obj, string parameterName)
        where T : class
{
    if(obj == null) throw new ArgumentNullException(parameterName);
}

ইত্যাদি

মূলত, স্থির কলগুলিতে কলগুলি খুব আক্ষরিক - অর্থাত্

string s = ...
if(s.IsNullOrEmpty()) {...}

হয়ে:

string s = ...
if(YourExtensionClass.IsNullOrEmpty(s)) {...}

স্পষ্টত কোন নাল চেক নেই যেখানে।


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

6
@ কনরাড: এটি প্রসঙ্গে নির্ভর করে। সি # সংকলক সাধারণত অ-ভার্চুয়াল পদ্ধতির জন্য এমনকি কল শ্লথ ব্যবহার করে, স্পষ্টভাবে নাল চেক প্রাপ্ত করতে obtain
জন স্কিটি

আমি কল এবং কলভার্ট ইল নির্দেশাবলী মধ্যে পার্থক্য উল্লেখ ছিল। একটি সম্পাদনায় আমি আসলে দুটি ওপকোড পৃষ্ঠাগুলি href করার চেষ্টা করেছি, তবে সম্পাদক লিঙ্কগুলিতে বিরক্ত হয়েছেন ...
মার্ক গ্র্যাভেল

2
আমি দেখছি না কীভাবে এক্সটেনশন পদ্ধতিগুলির এই ব্যবহারটি কোনও কার্যকর হতে পারে। এটি সম্পন্ন করার কারণে এটি ঠিক নয়, এবং বাইনারি ওয়ারিয়ার হিসাবে নীচে উল্লিখিত রয়েছে, এটি আমার কাছে কমপক্ষে বলার মতো খারাপ লাগছে like
ট্র্যাপ

3
@ ট্র্যাপ: আপনি বৈশিষ্ট্যযুক্ত-স্টাইল প্রোগ্রামিংয়ে থাকলে এই বৈশিষ্ট্যটি দুর্দান্ত।
রায় টিঙ্কার

50

মার্ক গ্র্যাভেল থেকে সঠিক উত্তর সংযোজন।

এই যুক্তিটি বাতিল হয়ে যাওয়ার বিষয়টি স্পষ্ট হলে আপনি সংকলকটির কাছ থেকে একটি সতর্কতা পেতে পারেন:

default(string).MyExtension();

রানটাইমে ভাল কাজ করে তবে সতর্কতা উত্পন্ন করে "Expression will always cause a System.NullReferenceException, because the default value of string is null"


32
কেন এটি "সর্বদা একটি সিস্টেমের কারণ করে দেয়। বাস্তবে কখন তা হবে না?
tpower

46
ভাগ্যক্রমে, আমরা প্রোগ্রামাররা কেবল ত্রুটি সম্পর্কে সতর্কতা না দিয়ে যত্ন করি: পি
জুলিয়ানআর

7
@ জুলিয়ানআর: হ্যাঁ, কিছু করেন, কেউ করেন না। আমাদের রিলিজ বিল্ড কনফিগারেশনে আমরা সতর্কতাগুলিকে ত্রুটি হিসাবে গণ্য করি। সুতরাং এটি ঠিক কাজ করে না।
স্টিফান স্টেইনগার

8
নোটের জন্য ধন্যবাদ; আমি এটি বাগের ডাটাবেসে পেয়ে যাব এবং আমরা এটি সি # 4.0 এর জন্য ঠিক করতে পারব কিনা তা আমরা দেখতে পাব। (কোন প্রতিশ্রুতি নেই - যেহেতু এটি একটি অবাস্তব কর্নার মামলা এবং নিছক একটি সতর্কবার্তা, আমরা সম্ভবত এটি সংশোধন করার জন্য
তর্ক করব

3
@ স্টেফান: যেহেতু এটি একটি ত্রুটিযুক্ত এবং "সত্য" সতর্কবার্তা নয়, আপনি কোডটি আপনার মুক্তির কাজটি পাস করার জন্য সতর্কবার্তাটি দমন করতে একটি # প্রগমা বিবৃতি ব্যবহার করতে পারেন।
মার্টিন আরএল

24

যেমন আপনি ইতিমধ্যে আবিষ্কার করেছেন, যেহেতু এক্সটেনশন পদ্ধতিগুলি কেবল স্ট্যাটিক পদ্ধতিগুলিকে মহিমান্বিত করা হয়, তাই এগুলি নিক্ষেপ না nullকরেই পাস হওয়া রেফারেন্স সহ ডাকা হবে NullReferenceException। তবে, যেহেতু তারা কলারের কাছে উদাহরণ পদ্ধতির মতো দেখায়, তাদেরও এ জাতীয় আচরণ করা উচিত । তারপরে আপনার বেশিরভাগ সময় thisপ্যারামিটারটি পরীক্ষা করা উচিত এবং যদি হয় তবে একটি ব্যতিক্রম ছুঁড়ে ফেলা উচিত nullnullনীচের উদাহরণগুলির মতো পদ্ধতিটি যদি পদ্ধতিটি স্পষ্টভাবে মানগুলির যত্ন নেয় এবং এর নামটি এটি যথাযথভাবে নির্দেশ করে তবে এটি করা ঠিক নয় :

public static class StringNullExtensions { 
  public static bool IsNullOrEmpty(this string s) { 
    return string.IsNullOrEmpty(s); 
  } 
  public static bool IsNullOrBlank(this string s) { 
    return s == null || s.Trim().Length == 0; 
  } 
}

কিছুদিন আগে আমি এ সম্পর্কে একটি ব্লগ পোস্টও লিখেছি ।


3
এটিকে ভোট দিয়েছি কারণ এটি সঠিক এবং আমার কাছে (এবং ভালভাবে লিখিত) অর্থবোধ করেছে, আমি @ মার্ক গ্র্যাভেলের উত্তরে বর্ণিত ব্যবহারটিও পছন্দ করি।
qxotk

17

একটি নাল এক্সটেনশন পদ্ধতিতে পাস করা হবে।

পদ্ধতিটি যদি পরীক্ষা না করে বস্তুটি অ্যাক্সেস করার চেষ্টা করে তবে এটি বাতিল হয়, তবে হ্যাঁ, এটি একটি ব্যতিক্রম ছুঁড়ে দেবে।

এখানে একজন লোক "ইসনুল" এবং "ইসনটনল" এক্সটেনশন পদ্ধতি লিখেছেন যা পরীক্ষা করে রেফারেন্সটি বাতিল বা না হয়। ব্যক্তিগতভাবে আমি মনে করি এটি একটি বিচ্যুতি এবং দিনের আলো দেখা উচিত হয়নি, তবে এটি পুরোপুরি বৈধ c #।


18
আসলে, আমার কাছে এটি একটি মৃতদেহ জিজ্ঞাসা করার মতো "আপনি কি বেঁচে আছেন" এবং "না" এর উত্তর পাওয়ার মতো। একটি মৃতদেহ কোনও প্রশ্নের জবাব দিতে পারে না, আপনি নাল বস্তুর কোনও পদ্ধতিতে "কল" করতেও সক্ষম হবেন না।
বাইনারি ওয়ারিয়র

14
আমি বাইনারি ওয়ারিয়ারের যুক্তির সাথে একমত নই, কারণ নাল রেফের বিষয়ে চিন্তা না করে এক্সটেনশানগুলি কল করতে সক্ষম হওয়ায় এটি অ্যানালজি কমেডি মানটির জন্য +1 :-)
টিম অবেল

10
আসলে, কখনও কখনও আপনি জানেন না যে কেউ মারা গেছে, তাই আপনি এখনও জিজ্ঞাসা করুন এবং ব্যক্তিটি উত্তর দিতে পারে, "না, কেবল আমার চোখ বন্ধ করে বিশ্রাম
নিচ্ছি

7
যখন আপনাকে বেশ কয়েকটি অপারেশন শৃঙ্খলাবদ্ধ করতে হবে (3+ বলুন), আপনি (কোনও পার্শ্ব-প্রতিক্রিয়া অনুমান করে) বোরিং বয়লারপ্লেট নাল-চেকিং কোডের বেশ কয়েকটি লাইনকে "নাল-সেফ" এক্সটেনশন পদ্ধতিগুলির সাথে একটি মার্জিতভাবে বেঁধে রাখা একটি-লাইনারে পরিণত করতে পারেন। (প্রস্তাবিত "।?" - অপারেটরের মতো, তবে স্বীকৃত হিসাবে মার্জিত নয়)) যদি এটি স্পষ্ট না হয় তবে একটি এক্সটেনশানটি "নাল-নিরাপদ" হয় তবে আমি সাধারণত "নিরাপদ" দিয়ে পদ্ধতিটির উপসর্গ করি, সুতরাং উদাহরণস্বরূপ যদি এটি একটি অনুলিপি হয়- পদ্ধতি, এর নামটি "SafeCopy" হতে পারে, এবং যুক্তিটি শূন্য হলে এটি নਾਲ ফিরে আসত।
আনোরজাকেন

3
আমি @ বাইনারি ওয়ারিয়রের উত্তর দিয়ে খুব হাসলাম চেকটি আমার মধ্যে ছিল, সক্রিয়ভাবে এটি লাথি মারছে কিনা তা দেখার জন্য it সুতরাং কোনও দেহ জানে না এটি মৃত কিনা এবং না, ডাব্লুএইচও চেক করে, জানে, এখন আপনি যুক্তি দিতে পারেন যে আপনি দেহকে "প্লাগইন" করতে পারেন এটির জন্য এটি একটি উপায় যা আপনাকে বলতে পারে এটি মারা গেছে বা না এবং আমার মতে এটি কি একটি এক্সটেনশন হয়।
জোরকাইন্ড

7

অন্যরা যেমন উল্লেখ করেছে, নাল রেফারেন্সে একটি এক্সটেনশন পদ্ধতি কল করার ফলে এই যুক্তিটি বাতিল হয়ে যায় এবং বিশেষ কিছু ঘটবে না। এটি গার্ড ক্লজগুলি লিখতে এক্সটেনশন পদ্ধতিগুলি ব্যবহার করার জন্য একটি ধারণা বাড়ায়।

আপনি উদাহরণগুলির জন্য এই নিবন্ধটি পড়তে পারেন: সাইক্লোমেটিক জটিলতা কীভাবে হ্রাস করবেন: গার্ড ক্লজ সংক্ষিপ্ত সংস্করণটি হ'ল:

public static class StringExtensions
{
    public static void AssertNonEmpty(this string value, string paramName)
    {
        if (string.IsNullOrEmpty(value))
            throw new ArgumentException("Value must be a non-empty string.", paramName);
    }
}

এটি স্ট্রিং ক্লাস এক্সটেনশন পদ্ধতি যা নাল রেফারেন্সে কল করা যেতে পারে:

((string)null).AssertNonEmpty("null");

কলটি ঠিক কাজ করে কারণ রানটাইম সফলভাবে এক্সটেনশন পদ্ধতিটিকে নাল রেফারেন্সে কল করবে। তারপরে আপনি অগোছালো সিনট্যাক্স ছাড়াই গার্ড ক্লজগুলি প্রয়োগ করতে এই এক্সটেনশন পদ্ধতিটি ব্যবহার করতে পারেন:

    public IRegisteredUser RegisterUser(string userName, string referrerName)
    {

        userName.AssertNonEmpty("userName");
        referrerName.AssertNonEmpty("referrerName");

        ...

    }

3

এক্সটেনশনমিডো স্ট্যাটিক, সুতরাং আপনি যদি এই মাইবজেক্টটিতে কিছু না করেন তবে সমস্যা হওয়া উচিত নয়, একটি দ্রুত পরীক্ষা এটি যাচাই করা উচিত :)


-1

আপনি যখন পাঠযোগ্য এবং উল্লম্ব হতে চান তখন কয়েকটি সোনার নিয়ম রয়েছে।

  • আইফেলের একটি কথাই বলছে যে কোনও পদ্ধতিতে এনক্যাপুলেটেড নির্দিষ্ট কোডটি কিছু ইনপুটটির বিরুদ্ধে কাজ করা উচিত, যদি কিছু পূর্বশর্ত পূরণ হয় এবং প্রত্যাশিত আউটপুট নিশ্চিত করে তবে কোডটি কার্যকর হয়

আপনার ক্ষেত্রে - ডিজাইনবাইক্র্যাক্টটি ভেঙে গেছে ... আপনি একটি নাল উদাহরণে কিছু যুক্তি সম্পাদন করতে যাচ্ছেন।

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