ইভেন্টগুলি সংজ্ঞায়িত করার সময় কেন আমাদের "ইভেন্ট" কীওয়ার্ডের প্রয়োজন?


108

আমি বুঝতে পারি না যে ইভেন্টগুলি সংজ্ঞায়িত করার সময় আমাদের "ইভেন্ট" কীওয়ার্ডের দরকার কেন, যখন আমরা "ইভেন্ট" কীওয়ার্ডটি ব্যবহার না করে একই কাজটি করতে পারি, কেবল প্রতিনিধিদের ব্যবহার করে।

যেমন

public delegate void CustomEventHandler(int a, string b);
public event CustomEventHandler customEvent;
customEvent += new CustomEventHandler(customEventHandler);
customEvent(1,"a"); // Raising the event

এখানে যদি আমি দ্বিতীয় ইভেন্ট থেকে "ইভেন্ট" কীওয়ার্ডটি সরিয়ে ফেলি, তবে আমিও প্রতিনিধিকে অনুরোধ করে ইভেন্টটি বাড়াতে পারি। কেউ দয়া করে আমাকে বলতে পারেন কেন এই ইভেন্টের কীওয়ার্ডটির প্রয়োজন?


ঠিক আছে যদি আপনি ইভেন্টের কীওয়ার্ডটি ব্যবহার করেন না এমন কেউ যারা ক্লাস অবজেক্টটি ব্যবহার করে সেই ইভেন্টটি অ্যাক্সেস করতে পারে সেটিকে এজেজক্লাসের মতো নূলে সেট করে। এটি আপনার অন্তর্নিহিত কোডটি ক্রাশ করবে। ইভেন্ট কীওয়ার্ড ব্যবহারকারীকে + = ব্যবহার করে প্রতিনিধিদের অনুরূপ কিছু নির্ধারণ করতে প্রয়োগ করে enforce
— সুমিত কাপাদিয়া

উত্তর:


141

ক্ষেত্রের মতো ইভেন্ট এবং প্রতিনিধি প্রকারের সর্বজনীন ক্ষেত্রগুলি দেখতে একই রকম, তবে বাস্তবে এটি খুব আলাদা।

একটি ইভেন্ট মূলত একটি সম্পত্তির মতো - এটি অ্যাড / রিমুথ পদ্ধতিগুলির একটি জুড়ি (কোনও সম্পত্তির প্রাপ্তি / সেটের পরিবর্তে)। আপনি যখন কোনও ক্ষেত্রের মতো ইভেন্ট ঘোষণা করেন (যেমন একটি যেখানে আপনি নিজেরাই বিডগুলি অ্যাড / অপসারণ নির্দিষ্ট করেন না) একটি সর্বজনীন ইভেন্ট তৈরি হয় এবং একটি ব্যক্তিগত ব্যাকিং ফিল্ড। এটি আপনাকে ইভেন্টটি ব্যক্তিগতভাবে বাড়াতে দেয়, তবে সর্বজনীন সাবস্ক্রিপশনের অনুমতি দেয়। জন প্রতিনিধি ক্ষেত্রের সাথে, যে কোনও ব্যক্তি অন্য লোকের ইভেন্ট হ্যান্ডলারগুলি সরিয়ে ফেলতে পারেন, ইভেন্টটি নিজেরাই উত্থাপন করতে পারেন ইত্যাদি - এটি একটি encapsulation দুর্যোগ।

ইভেন্টগুলি সম্পর্কে আরও তথ্যের জন্য (এবং প্রতিনিধিরা) এই বিষয়ে আমার নিবন্ধটি পড়ুন । (এক পর্যায়ে আমার এটি সি # 4 এর জন্য আপডেট করতে হবে, যা ফিল্ডের মতো ইভেন্টগুলিকে খুব সামান্য পরিবর্তন করে it যদিও এর সূচনাটি এখনও সঠিক)


17
এটি এমএসডিএন এর অফিসিয়াল এক-লাইন ব্যাখ্যার চেয়ে হাজার গুণ ভাল: 'ইভেন্ট কীওয়ার্ডটি প্রকাশক শ্রেণিতে কোনও ইভেন্ট ঘোষণার জন্য ব্যবহৃত হয়।'
— কাউলিনেটর

36

ইভেন্ট কীওয়ার্ডটি 3 বিভিন্ন জিনিস করে:

  1. আপনি ইন্টারফেসে কোনও ইভেন্টের সংজ্ঞা দিতে পারবেন, যদিও আপনি ইন্টারফেসে নিয়মিত ক্ষেত্রগুলি নির্ধারণ করতে পারবেন না।
  2. এটা তোলে দৃশ্যমানতা পরিবর্তন =এবং ()ব্যক্তিগত হিসাবে অপারেটার (নিয়োগ এবং আবাহন), যাতে শুধুমাত্র ধারণকারী বর্গ ঘটনা ডাকা বা ওভাররাইড সব পদ্ধতি এটি অন্তর্ভুক্ত করতে পারেন। -=এবং +=অপারেটরদের এখনও বর্গ এটা সংজ্ঞায়িত (তারা পেতে এক্সেস পরিবর্তক আপনি ইভেন্টের পাশে লিখেছে) বাইরে থেকে একটি ইভেন্টে প্রার্থনা করা যেতে পারে।
  3. এছাড়াও আপনি পথ ওভাররাইড করতে পারে -=এবং +=ইভেন্টের আচরণ।

2
আপনি> এমএসডিএন ধন্যবাদ।
— এম আজ्योকসুল

26

অন্য উত্তরগুলি ঠিক আছে; আমি ভাবতে ভাবতে অন্য কিছু যুক্ত করতে চাই।

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

class C
{
    private int z;
    public readonly Func<int, int> M = (int x)=>{ return x+z; }
    // ... and so on
}

?

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


4
কি দারুন! এটা মনে করিয়ে দেয় কেন আমি সি # কে ভালবাসি! আমি যে সকল ভাষার সাথে কাজ করেছি সেগুলির মধ্যে এর মধ্যে কমপ্যাক্টনেস, নমনীয়তা এবং পাঠযোগ্য শব্দার্থতত্ত্বের সঠিক ভারসাম্য রয়েছে। একমাত্র তুলনামূলক ভাষা হ'ল অবজেক্ট পাস্কাল।
— এটিএল_ডিইভি

1
@ATL_DEV: এর একটি কারণ আছে। সি # ভাষার স্থপতি অ্যান্ডারস হিজলসবার্গ আগে ডেল্ফির স্থপতি ছিলেন, যা ছিল অবজেক্ট পাস্কেলের উপর ভিত্তি করে একটি ভাষা।
— এরিক লিপার্ট

9

এটি আংশিক প্রয়োজন কারণ আপনি eventকীওয়ার্ডটি বাদ দিলে এটি এনক্যাপসুলেশনটি ভেঙে যায়। যদি এটি কেবল সর্বজনীন মাল্টিকাস্টের প্রতিনিধি হয় তবে যে কেউ এটিকে ডাকতে পারেন, এটিকে শূন্য করতে পারেন বা এটির সাথে হস্তক্ষেপ করতে পারেন। যদি বলা একটি শ্রেণীর MailNotifierউপস্থিতি থাকে এবং এটিতে কোনও ইভেন্ট ডাকা হয় MailReceived, তবে অন্য ধরণের লোকেরা কল করার মাধ্যমে সেই ঘটনাটি চালিত করতে সক্ষম হয় না mailNotifier.MailReceived();

অন্যদিকে, আপনি কেবল সেই ক্ষেত্রের সাথে হস্তক্ষেপ করতে এবং 'সংক্ষেত্রের মতো' ইভেন্টগুলিকে প্রকারের ইভেন্ট থেকে সংজ্ঞায়িত করতে পারেন।

যদি আপনি আপনার ইভেন্টের আমন্ত্রণটি ব্যক্তিগত রাখতে চান, তবে আপনাকে এরকম কিছু করা বন্ধ করার কিছুই নেই:

public class MyClassWithNonFieldLikeEvent
{
   private CustomEventHandler m_delegate;

   public void Subscribe(CustomEventHandler handler) 
   {
      m_delegate += handler;        
   }

   public void Unsubscribe(CustomEventHandler handler)
   {          
      m_delegate -= handler;
   }

   private void DoSomethingThatRaisesEvent()
   {
      m_delegate.Invoke(...);
   }       
}

... তবে ক্ষেত্রের মতো ইভেন্টগুলি ইতিমধ্যে আমাদের যা দেবে তা করার জন্য (পুরোপুরি কম বেশি) কোডই এটি সম্পূর্ণ লোড।


ডিজাইনারদের মতো ব্যবহার করাও শক্ত হবে ... আপনি মূলত পদ্ধতিগুলির জন্য নামকরণের কনভেনশনের উপর নির্ভর করে থাকবেন না, "এটি একটি ইভেন্ট" বলে জনসাধারণের মেটাডেটা না করে।
— জন স্কিটি

3

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

আরও তথ্যের জন্য এই ব্লগ পোস্ট দেখুন ।


2
আপনার ইভেন্ট এবং প্রতিনিধিদের তুলনা করা উচিত নয় - একটি প্রতিনিধি প্রকারের সাথে ইভেন্ট এবং সর্বজনীন ক্ষেত্রের তুলনা করুন । এবং না, ফ্রেমওয়ার্কটিতে সেই স্বাক্ষরটির জন্য ইভেন্টগুলির প্রয়োজন হয় না । আপনার পছন্দ মতো যে কোনও প্রতিনিধি প্রকারের একটি ইভেন্ট তৈরি করতে পারেন।
— জন স্কিটি

3

প্রতিনিধি একটি রেফারেন্স টাইপ। এটি মাল্টিকাস্টডেলিগেটের উত্তরাধিকারী । ইভেন্ট একটি সংশোধক। ঘটনাপ্রতিনিধিদের জন্য একটি বিশেষ পরিবর্তনকারী is এটি কিছু ফাংশন / পদ্ধতি অ্যাক্সেসযোগ্যতার পরিবর্তন করে, উদাহরণস্বরূপ ইনভোক পদ্ধতি। সংশোধক ইভেন্ট দ্বারা সংশোধন করার পরে, একটি প্রতিনিধি উদাহরণ একটি নতুন ধারণা "ইভেন্ট" হয়ে ওঠে। সুতরাং ইভেন্টটি কেবলমাত্র একটি পরিবর্তিত প্রতিনিধি। আপনি সরাসরি রেফারেন্স পরিবর্তন করতে পারবেন না বা ইভেন্টটিকে শ্রেণীর বাইরে ইভেন্টের জন্য আবেদন করতে পারেন যেখানে ইভেন্টটি সংজ্ঞায়িত হয়েছিল, তবে আপনি রেফারেন্স পরিবর্তন করতে পারেন বা একটি সাধারণ প্রতিনিধি উদাহরণটি চাইতে পারেন। ইভেন্ট অতিরিক্ত সুরক্ষা সরবরাহ করে, যাতে ইভেন্টটিতে আরও সুরক্ষা বৈশিষ্ট্য থাকে। আপনি যখন ইভেন্টটি সংজ্ঞায়িত করা হয়েছিল এমন শ্রেণীর বাইরে গেলে, আপনার ইভেন্টে "+ =" এবং "- =" দুটি ধরণের অপারেশন করার অনুমতি দেওয়া হয়। তবে আপনি সাধারণ প্রতিনিধি উদাহরণের সমস্ত পাবলিক ফিল্ড, সম্পত্তি, পদ্ধতি ইত্যাদি অ্যাক্সেস করতে পারেন। এখানে একটি উদাহরণ দেওয়া হল:

namespace DelegateEvent
{
    //the following line behave as a class. It is indeed a reference type
    public delegate void MyDelegate(string inputs);

    //The following line is illegal. It can only be an instance. so it cannot be directly under namespace
    //public event MyDelegate MyEvent;


    public class MyClassA
    {
        public event MyDelegate MyEventA;
        public MyDelegate MyDelegateA;


        System.Threading.ManualResetEvent MyResetEvent = new System.Threading.ManualResetEvent(false);
        public void TryToDoSomethingOnMyDelegateA()
        {
            if (MyDelegateA != null)
            {
                //User can assecc all the public methods.
                MyDelegateA("I can invoke detegate in classA");         //invoke delegate
                MyDelegateA.Invoke("I can invoke detegate in classA");  //invoke delegate
                IAsyncResult result = MyDelegateA.BeginInvoke("I can invoke detegate in classA", MyAsyncCallback, MyResetEvent);    //Async invoke
                //user can check the public properties and fields of delegate instance
                System.Reflection.MethodInfo delegateAMethodInfo = MyDelegateA.Method;

                MyDelegateA = testMethod;                   //reset reference
                MyDelegateA = new MyDelegate(testMethod);   //reset reference
                MyDelegateA = null;                         //reset reference


                MyDelegateA += testMethod;                  //Add delegate
                MyDelegateA += new MyDelegate(testMethod);  //Add delegate
                MyDelegateA -= testMethod;                  //Remove delegate
                MyDelegateA -= new MyDelegate(testMethod);  //Remove delegate
            }
        }

        public void TryToDoSomethingOnMyEventA()
        {
            if (MyEventA != null)
            {
                MyEventA("I can invoke Event in classA");           //invoke Event
                MyEventA.Invoke("I can invoke Event in classA");    //invoke Event
                IAsyncResult result = MyEventA.BeginInvoke("I can invoke Event in classA", MyAsyncCallback, MyResetEvent);      //Async invoke
                //user can check the public properties and fields of MyEventA
                System.Reflection.MethodInfo delegateAMethodInfo = MyEventA.Method;


                MyEventA = testMethod;                   //reset reference
                MyEventA = new MyDelegate(testMethod);   //reset reference
                MyEventA = null;                         //reset reference


                MyEventA += testMethod;                  //Add delegate
                MyEventA += new MyDelegate(testMethod);  //Add delegate
                MyEventA -= testMethod;                  //Remove delegate
                MyEventA -= new MyDelegate(testMethod);  //Remove delegate
            }
        }

        private void MyAsyncCallback(System.IAsyncResult result)
        {
            //user may do something here
        }
        private void testMethod(string inputs)
        {
            //do something
        }

    }
    public class MyClassB
    {
        public MyClassB()
        {
            classA = new MyClassA();
        }
        public MyClassA classA;
        public string ReturnTheSameString(string inputString)
        {
            return inputString;
        }


        public void TryToDoSomethingOnMyDelegateA()
        {
            if (classA.MyDelegateA != null)
            {
                //The following two lines do the same job --> invoke the delegate instance
                classA.MyDelegateA("I can invoke delegate which defined in class A in ClassB");
                classA.MyDelegateA.Invoke("I can invoke delegate which defined in class A in ClassB");
                //Async invoke is also allowed

                //user can check the public properties and fields of delegate instance
                System.Reflection.MethodInfo delegateAMethodInfo = classA.MyDelegateA.Method;

                classA.MyDelegateA = testMethod;                   //reset reference
                classA.MyDelegateA = new MyDelegate(testMethod);   //reset reference
                classA.MyDelegateA = null;                         //reset reference


                classA.MyDelegateA += testMethod;                  //Add delegate
                classA.MyDelegateA += new MyDelegate(testMethod);  //Add delegate
                classA.MyDelegateA -= testMethod;                  //Remove delegate
                classA.MyDelegateA -= new MyDelegate(testMethod);  //Remove delegate

            }

        }
        public void TryToDoSomeThingMyEventA()
        {
            //check whether classA.MyEventA is null or not is not allowed
            //Invoke classA.MyEventA is not allowed
            //Check properties and fields of classA.MyEventA is not allowed
            //reset classA.MyEventA reference is not allowed

            classA.MyEventA += testMethod;                  //Add delegate
            classA.MyEventA += new MyDelegate(testMethod);  //Add delegate
            classA.MyEventA -= testMethod;                  //Remove delegate
            classA.MyEventA -= new MyDelegate(testMethod);  //Remove delegate
        }

        private void testMethod(string inputs)
        {
            //do something here
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.