সি # তে শূন্য না হলে পদ্ধতি কল


107

এই বিবৃতিটি কি কোনওভাবে সংক্ষিপ্ত করা সম্ভব?

if (obj != null)
    obj.SomeMethod();

কারণ আমি এটি অনেক লিখতে পেরেছি এবং এটি বেশ বিরক্তিকর হয়। আমি কেবলমাত্র নাল অবজেক্ট প্যাটার্নটি বাস্তবায়নের জন্যই ভাবতে পারি , তবে আমি প্রতিবার যা করতে পারি তা নয় এবং এটি বাক্য সংশ্লেষকে সংক্ষিপ্ত করার কোনও সমাধান নয়।

এবং ইভেন্টগুলির সাথে একই রকম সমস্যা, যেখানে

public event Func<string> MyEvent;

এবং তারপর প্রার্থনা

if (MyEvent != null)
    MyEvent.Invoke();

41
আমরা সি # 4 এ একটি নতুন অপারেটর যুক্ত করার বিষয়টি বিবেচনা করেছি: "আপত্তি।? সোম্মেথোদ ()" এর অর্থ "আপত্তি নাল না হলে সোমমথোদকে কল করুন, অন্যথায়, নাল ফেরান"। দুর্ভাগ্যক্রমে এটি আমাদের বাজেটের সাথে খাপ খায়নি তাই আমরা কখনই এটি প্রয়োগ করি নি।
এরিক লিপার্ট

@ এরিক: এই মন্তব্যটি কি এখনও বৈধ? আমি কোথাও দেখেছি যে এটি 4.0 এর সাথে পাওয়া যায়?
CharithJ

@ চরিতজে: না এটি কখনও বাস্তবায়িত হয়নি।
এরিক লিপার্ট

4
@ চরিতজে: আমি নাল কোয়েলসিং অপারেটরের উপস্থিতি সম্পর্কে অবহিত। এটি ডার্ট যা চায় তা করে না; তিনি একটি উত্তোলিত থেকে নুলযোগ্য সদস্য অ্যাক্সেস অপারেটর চান। : (।। এবং এইভাবে, আপনার আগের মন্তব্য নাল কোয়ালেসিং অপারেটর একটি ভুল চরিত্রায়ন আপনি বলতে "? M.Value লেখা যেতে পারে বনাম = মি ?? Y বনাম = মি == নাল Y" বোঝানো দেয়)
এরিক লিপার্ট

4
নতুন পাঠকদের জন্য: সি # .0.০ টি প্রয়োগ?।, তাই এক্স? .আই?
ডেভিড

উত্তর:


166

সি # 6 থেকে, আপনি কেবল ব্যবহার করতে পারেন:

MyEvent?.Invoke();

বা:

obj?.SomeMethod();

?.নাল-প্রচারের অপারেটর, এবং কারণ হবে .Invoke()স্বল্প circuited করা যখন প্রতীক হয় null। অপারেন্ডটি কেবল একবার অ্যাক্সেস করা যায়, সুতরাং "চেক এবং অনুরোধের মধ্যে মান পরিবর্তন" হওয়ার ঝুঁকি নেই।

===

সি # 6 এর পূর্বে, না: কোনও ব্যতিক্রম ছাড়া নাল-নিরাপদ যাদু নেই; এক্সটেনশন পদ্ধতি - উদাহরণস্বরূপ:

public static void SafeInvoke(this Action action) {
    if(action != null) action();
}

এখন এটি বৈধ:

Action act = null;
act.SafeInvoke(); // does nothing
act = delegate {Console.WriteLine("hi");}
act.SafeInvoke(); // writes "hi"

ইভেন্টগুলির ক্ষেত্রে, রেস-কন্ডিশনটি সরিয়ে ফেলার এটির সুবিধাও রয়েছে, অর্থাত্ আপনার অস্থায়ী পরিবর্তনশীল প্রয়োজন হবে না। তাই সাধারণত আপনার প্রয়োজন:

var handler = SomeEvent;
if(handler != null) handler(this, EventArgs.Empty);

কিন্তু সঙ্গে:

public static void SafeInvoke(this EventHandler handler, object sender) {
    if(handler != null) handler(sender, EventArgs.Empty);
}

আমরা সহজভাবে ব্যবহার করতে পারি:

SomeEvent.SafeInvoke(this); // no race condition, no null risk

4
'আমি এই সম্পর্কে সামান্য বিরোধ। কোনও অ্যাকশন বা ইভেন্ট হ্যান্ডলারের ক্ষেত্রে - যা সাধারণত আরও স্বতন্ত্র - এটি কিছুটা অর্থপূর্ণ। যদিও আমি নিয়মিত পদ্ধতির জন্য এনক্যাপসুলেশনটি ভাঙ্গি না। এটি পৃথক, স্থিতিশীল শ্রেণিতে পদ্ধতিটি তৈরি করার ইঙ্গিত দেয় এবং আমি মনে করি না যে সম্পূর্ণভাবে এনক্যাপসুলেশন হ্রাস করা এবং পাঠযোগ্যতা / কোড সংস্থা
হ্রাস করা

@ টানফসন - সত্যই; তবে আমার বক্তব্যটি হ'ল এটিই কেবল কাজ করবে যেখানে আমি এটি জানি। এবং প্রশ্ন নিজেই প্রতিনিধি / ইভেন্টগুলির বিষয় উত্থাপন করে।
মার্ক Gravell

এই কোডটি কোথাও একটি বেনামি পদ্ধতি তৈরির কাজ শেষ করে, যা কোনও ব্যতিক্রমের স্ট্যাক ট্রেসকে সত্যিই মেসেজ করে। বেনাম পদ্ধতির নাম দেওয়া কি সম্ভব? ;)
সিসভে

@ মার্কগ্রাভেল এটিকে নাল কন্ডিশনাল অপারেটর বলা হয় না।
রায়লাভলেস

4
@ মার্কু এটি হওয়া উচিত ?.- ভিবি 14 এবং তার উপরে
মার্ক গ্র্যাভেল

27

আপনি কি খুঁজছেন নাল-শর্তসাপেক্ষ (নয় "কোয়ালেসিং") অপারেটর: ?.। এটি সি # 6 হিসাবে উপলব্ধ।

আপনার উদাহরণ হবে obj?.SomeMethod();। আপত্তি যদি নাল হয় তবে কিছুই হয় না। যখন পদ্ধতিটিতে আর্গুমেন্ট থাকে, উদাহরণস্বরূপ obj?.SomeMethod(new Foo(), GetBar());আর্গুমেন্ট objনাল হয় তবে তা মূল্যায়ন করা হয় না , যুক্তিগুলির মূল্যায়ন করলে পার্শ্ব প্রতিক্রিয়া হবে।

এবং শৃঙ্খলা সম্ভব: myObject?.Items?[0]?.DoSomething()


4
এটি চমৎকার. এটি লক্ষণীয় যে এটি একটি সি # 6 বৈশিষ্ট্য ... (যা আপনার ভিএস ২০১৫ বিবৃতি থেকে অন্তর্ভুক্ত করা হবে তবে এখনও লক্ষণীয়) :)
কাইল গুড

10

একটি দ্রুত সম্প্রসারণ পদ্ধতি:

    public static void IfNotNull<T>(this T obj, Action<T> action, Action actionIfNull = null) where T : class {
        if(obj != null) {
            action(obj);
        } else if ( actionIfNull != null ) {
            actionIfNull();
        }
    }

উদাহরণ:

  string str = null;
  str.IfNotNull(s => Console.Write(s.Length));
  str.IfNotNull(s => Console.Write(s.Length), () => Console.Write("null"));

বা বিকল্পভাবে:

    public static TR IfNotNull<T, TR>(this T obj, Func<T, TR> func, Func<TR> ifNull = null) where T : class {
        return obj != null ? func(obj) : (ifNull != null ? ifNull() : default(TR));
    }

উদাহরণ:

    string str = null;
    Console.Write(str.IfNotNull(s => s.Length.ToString());
    Console.Write(str.IfNotNull(s => s.Length.ToString(), () =>  "null"));

আমি একজন ছিল এক্সটেনশন পদ্ধতি এটা করতে প্রয়াস এবং আমি কাছাকাছি একই কোড দিয়ে শেষ পর্যন্ত। যাইহোক, এই বাস্তবায়নের ক্ষেত্রে সমস্যাটি হ'ল এটি কোনও মূল্য ধরণের প্রত্যাশার মত প্রকাশের সাথে কাজ করবে না। সুতরাং এটির জন্য একটি দ্বিতীয় পদ্ধতি থাকতে হয়েছিল।
ওড়াদ

4

ইভেন্টগুলি খালি ডিফল্ট প্রতিনিধি দিয়ে শুরু করা যেতে পারে যা কখনই সরানো হয় না:

public event EventHandler MyEvent = delegate { };

নাল চেক করার দরকার নেই।

[ আপডেট করুন , বেভানকে এটি নির্দেশ করার জন্য ধন্যবাদ]

সম্ভাব্য পারফরম্যান্স প্রভাব সম্পর্কে সচেতন থাকুন। আমি যে দ্রুত মাইক্রো বেনমার্কটি করেছিলাম তা ইঙ্গিত করে যে কোনও গ্রাহকবিহীন ইভেন্ট হ্যান্ডেল করা "ডিফল্ট প্রতিনিধি" প্যাটার্নটি ব্যবহার করার সময় 2-3 গুণ ধীর হয়। (আমার দ্বৈত কোর 2.5GHz ল্যাপটপে যার অর্থ 279ms: 78 মিলিয়ন সাবস্ক্রাইব করা ইভেন্টগুলি উত্থাপনের জন্য 785ms))। অ্যাপ্লিকেশন হট স্পটগুলির জন্য, এটি বিবেচনার জন্য সমস্যা হতে পারে।


4
সুতরাং, আপনি একটি খালি প্রতিনিধিকে আহ্বান করে নাল চেক এড়াতে পারেন ... কয়েকটি কী-স্ট্রোক সংরক্ষণ করার জন্য মেমরি এবং সময় উভয়ের একটি পরিমাপযোগ্য ত্যাগ? ওয়াইএমএমভি, তবে আমার কাছে একটি দুর্বল বাণিজ্য বন্ধ।
বেভান

আমি এমন মানদণ্ডও দেখেছি যা দেখায় যে একাধিক প্রতিনিধি এতে কেবল একটির চেয়ে সাবস্ক্রাইব করে একটি ইভেন্ট শুরু করা যথেষ্ট ব্যয়বহুল।
গ্রেগ ডি


2

আয়ান গ্রিফিথসের এই নিবন্ধটি যে সমস্যার সমাধান করেছে তার দুটি পৃথক সমাধান দেয় যা আপনার ব্যবহার করা উচিত নয় t


4
এবং এই নিবন্ধটির লেখক হিসাবে বক্তব্য রেখে, আমি যুক্ত করব যে আপনার এখন অবশ্যই এটি ব্যবহার করা উচিত নয় যে সি # 6 নাল শর্তসাপেক্ষ অপারেটরদের (?। এবং। []) দিয়ে বাক্সের বাইরে সমাধান করে।
ইয়ান গ্রিফিথস

2

প্রস্তাবিতগুলির মতো সিটারিং এক্সটেনশন পদ্ধতিটি সত্যই জাতিদের শর্তগুলির সাথে সমস্যাগুলি সমাধান করে না, বরং এগুলি গোপন করে।

public static void SafeInvoke(this EventHandler handler, object sender)
{
    if (handler != null) handler(sender, EventArgs.Empty);
}

যেমন বলা হয়েছে এই কোডটি অস্থায়ী পরিবর্তনশীল সহ সমাধানের মার্জিত সমতুল্য, তবে ...

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

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

থ্রেড সুরক্ষিততা নিশ্চিত করার একমাত্র পরিচিত উপায় হ'ল ইভেন্টটির প্রেরকের জন্য লক স্টেটমেন্ট ব্যবহার করা। এটি নিশ্চিত করে যে সমস্ত সাবস্ক্রিপশন \ আনসাবস্ক্রিপশন \ অনুরোধটি সিরিয়ালাইজড।

আরও সঠিক লক হওয়ার জন্য একই সিঙ্ক অবজেক্টটিতে অ্যাড ব্যবহার করতে হবে or ইভেন্ট অ্যাকসেসর পদ্ধতিগুলি মুছুন যা ডিফল্ট 'এটি' be


এটি রেফার করা রেসের শর্ত নয়। প্রতিযোগিতার শর্তটি যদি (MyEvent! = নাল) হয় তবে // MyEvent এখন MyEvent.Invoke (); // MyEvent এখন নাল, খারাপ জিনিস ঘটে তাই এই প্রতিযোগিতার শর্তের সাথে আমি কোনও async ইভেন্ট হ্যান্ডলার লিখতে পারি না যা কাজের গ্যারান্টিযুক্ত। তবে আপনার 'রেসের শর্ত'-এর সাথে, আমি অসিঙ্ক ইভেন্ট হ্যান্ডলারটি লিখতে পারি যা কাজের গ্যারান্টিযুক্ত। অবশ্যই গ্রাহক এবং সাবস্ক্রাইবদের কলগুলি সিঙ্ক্রোনাস হওয়া দরকার, বা লক কোডটি সেখানে প্রয়োজনীয়।
jyoung

প্রকৃতপক্ষে. এই সমস্যাটির বিষয়ে আমার বিশ্লেষণটি এখানে পোস্ট করা হয়েছে: ব্লগস.এমএসএনএন
এরিক লিপার্ট

2

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

এক্সটেনশন পদ্ধতি (ifNotNull পদ্ধতি)


1

সম্ভবত ভাল না তবে আমার মতে আরও পঠনযোগ্য হ'ল একটি এক্সটেনশন পদ্ধতি তৈরি করা

public static bool IsNull(this object obj) {
 return obj == null;
}

4
কি return obj == nullগড়। এটি কী ফিরে আসবে
হামদ খান

4
এর মানে যদি objহয় nullপদ্ধতি ফিরে আসবে true, আমি মনে করি।
জোয়েল

4
এটি কীভাবে প্রশ্নের উত্তর দেয়?
কুগেল

দেরিতে জবাব, তবে আপনি কি নিশ্চিত যে এটি এমনকি কার্যকর হবে? আপনি যে কোনও বস্তুর উপর কোনও এক্সটেনশন পদ্ধতি কল করতে পারেন null? আমি নিশ্চিত যে এটি ধরণের নিজস্ব পদ্ধতিগুলির সাথে কাজ করে না, তাই আমি সন্দেহ করি এটি এক্সটেনশন পদ্ধতিগুলির সাথেও কাজ করবে। আমি একটি বস্তু সবচেয়ে ভালো উপায় চেক করতে বিশ্বাস হয় null হয় obj is null। দুর্ভাগ্যবশত, একটি বস্তুর চেক করতে নয় না nullবন্ধনীর মধ্যে মোড়ানো, যা দুর্ভাগ্যজনক প্রয়োজন।
নাটিয়িক্স

0

আমি এই জেনেরিক এক্সটেনশনটি ব্যবহার করেছি যা আমি ব্যবহার করি।

public static class ObjectExtensions {
    public static void With<T>(this T value, Action<T> todo) {
        if (value != null) todo(value);
    }
}

তারপরে আমি নীচের মত এটি ব্যবহার।

string myString = null;
myString.With((value) => Console.WriteLine(value)); // writes nothing
myString = "my value";
myString.With((value) => Console.WriteLine(value)); // Writes `my value`

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