প্রতিনিধি এবং ইভেন্টের মধ্যে পার্থক্য কী?


315

প্রতিনিধি এবং একটি ইভেন্টের মধ্যে পার্থক্য কী? উভয়ই কার্যকর করা যেতে পারে এমন ফাংশনগুলির রেফারেন্স রাখে না?



2
উদাহরণস্বরূপ এটি ব্যাখ্যা করে unityক্যজেক.কম
রাহুল ললিত

উত্তর:


280

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


43
যদি অবশ্যই, এই সুরক্ষা স্তরটি "ক্লায়েন্ট" (সংজ্ঞায়িত শ্রেণি / কাঠামোর বাইরে কোড) প্রতিনিধিকে আহ্বান করা থেকে এবং কোনওভাবেই প্রতিনিধিটিকে ইভেন্টটির "পিছনে" প্রাপ্তি থেকে বাধা দেয়।
জেপ্পে স্টিগ নীলসন

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

3
@ এমএমসিডোল আপনি কি তার ব্যাখ্যা দেওয়ার জন্য একটি উদাহরণ দিতে পারেন?
বিবেক নুনা

102

পার্থক্যগুলি বুঝতে আপনি এই 2 টি উদাহরণটি দেখতে পারেন

প্রতিনিধিদের সাথে উদাহরণ (এই ক্ষেত্রে, একটি অ্যাকশন - এটি এমন একধরণের প্রতিনিধি যা কোনও মূল্য ফেরায় না)

public class Animal
{
    public Action Run {get; set;}

    public void RaiseEvent()
    {
        if (Run != null)
        {
            Run();
        }
    }
}

প্রতিনিধি ব্যবহার করতে, আপনার এই জাতীয় কিছু করা উচিত:

Animal animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();

এই কোডটি ভাল কাজ করে তবে আপনার কিছু দুর্বল দাগ থাকতে পারে।

উদাহরণস্বরূপ, আমি যদি এটি লিখি:

animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;

কোডের শেষ লাইনের সাথে আমি পূর্বের আচরণগুলি কেবল একটি অনুপস্থিতের সাথে ওভাররাইড +করেছি ( =পরিবর্তে আমি ব্যবহার করেছি +=)

আর একটি দুর্বল স্পট হ'ল আপনার Animalক্লাসটি ব্যবহার করে এমন প্রতিটি শ্রেণি RaiseEventকেবল এটি কল করতে পারে animal.RaiseEvent()

এই দুর্বল দাগগুলি এড়াতে eventsআপনি সি # তে ব্যবহার করতে পারেন ।

আপনার প্রাণী শ্রেণিটি এভাবে পরিবর্তিত হবে:

public class ArgsSpecial : EventArgs
{
    public ArgsSpecial (string val)
    {
        Operation=val;
    }

    public string Operation {get; set;}
} 

public class Animal
{
    // Empty delegate. In this way you are sure that value is always != null 
    // because no one outside of the class can change it.
    public event EventHandler<ArgsSpecial> Run = delegate{} 

    public void RaiseEvent()
    {  
         Run(this, new ArgsSpecial("Run faster"));
    }
}

ইভেন্ট কল করতে

 Animal animal= new Animal();
 animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
 animal.RaiseEvent();

পার্থক্য:

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

মন্তব্য:

ইভেন্টহ্যান্ডলারকে নিম্নলিখিত প্রতিনিধি হিসাবে ঘোষণা করা হয়েছে:

public delegate void EventHandler (object sender, EventArgs e)

এটি একটি প্রেরক (অবজেক্ট টাইপের) এবং ইভেন্টের আর্গুমেন্টগুলি লাগে। প্রেরক যদি স্থির পদ্ধতি থেকে আসে তবে তা বাতিল হয়।

এই উদাহরণ, যা ব্যবহার করে EventHandler<ArgsSpecial>, EventHandlerপরিবর্তে ব্যবহার করেও লেখা যেতে পারে be

পড়ুন এখানে EventHandler সম্পর্কে নথিপত্রের জন্য


7
"আমি আপনার ক্লাসের বাইরের কেউ ইভেন্টটি বাড়িয়ে তুলতে পারে না" না হওয়া পর্যন্ত সবকিছু দুর্দান্ত দেখাচ্ছিল। ওটার মানে কি? যে RaiseEventকলিং পদ্ধতির animalইভেন্ট ব্যবহার করা কোডটিতে এমন কোনও উদাহরণের অ্যাক্সেস রয়েছে ততক্ষণ কেউ কল করতে পারবেন না ?
dance2die

11
@ সং ইভেন্টগুলি কেবলমাত্র ক্লাসের অভ্যন্তর থেকে উত্থিত হতে পারে, সম্ভবত আমি এটি ব্যাখ্যা করে পরিষ্কার ছিলাম না। ইভেন্টগুলির সাহায্যে আপনি সেই অনুষ্ঠানটিকে কল করতে পারেন যা ইভেন্টটি বাড়িয়ে তোলে (এনক্যাপসুলেশন), তবে এটি কেবল এটি সংজ্ঞায়িত করে শ্রেণীর ভিতরে থেকে উঠতে পারে। আমি পরিষ্কার না হলে আমাকে জানান।
চমত্কার

1
"ইভেন্টগুলি সরাসরি বরাদ্দ করা যায় না।" আমি আপনাকে ভুল বুঝতে না পারলে এটি সত্য নয়। এখানে একটি উদাহরণ রয়েছে: gist.github.com/Chiel92/36bb3a2d2ac7dd511b96
দশ ব্রিনকে

2
@ ফ্যাবি, আপনার অর্থ এই যে ঘটনাটি জনসমক্ষে ঘোষণা করা সত্ত্বেও আমি এখনও পারি না animal.Run(this, new ArgsSpecial("Run faster");?
পাপ

1
@ চিল্টেনব্রিংক অবশ্যই ইভেন্টটি ক্লাসের সদস্যদের মধ্যে বরাদ্দ করা যেতে পারে ... তবে অন্যথায় নয়।
জিম বাল্টার

93

সিনথেটিক এবং অপারেশনাল বৈশিষ্ট্যগুলি ছাড়াও একটি শব্দার্থক পার্থক্য রয়েছে।

প্রতিনিধিরা, ধারণামূলকভাবে, ফাংশন টেম্পলেটগুলি; অর্থাৎ, তারা একটি চুক্তি প্রকাশ করে একটি প্রতিনিধিদলের "প্রকার" বিবেচনা করার জন্য একটি ফাংশন অবশ্যই মেনে চলতে হবে।

ইভেন্টগুলি প্রতিনিধিত্ব করে ... ভাল, ইভেন্টগুলি। তারা যখন কিছু ঘটে তখন কাউকে সতর্ক করার উদ্দেশ্যে এবং হ্যাঁ, তারা একটি প্রতিনিধি সংজ্ঞা মেনে চলে তবে তারা একই জিনিস নয়।

এমনকি যদি তারা ঠিক একই জিনিস ছিল (সিনট্যাক্টিকালি এবং আইএল কোডে) তখনও শব্দার্থগত পার্থক্য থাকবে। সাধারণভাবে আমি দুটি ভিন্ন ধারণার জন্য দুটি আলাদা নাম রাখতে পছন্দ করি, এমনকি যদি সেগুলি একইভাবে প্রয়োগ করা হয় (তবে এর অর্থ এই নয় যে আমি একই কোডটি দুটিবারই পেতে চাই)।


8
প্রতিনিধিদের দুর্দান্ত বর্ণনা।
সাম্পসন

1
সুতরাং আমরা কি বলতে পারি যে কোনও অনুষ্ঠান একটি প্রতিনিধিদের "বিশেষ" ধরণের?
পাপ

আমি আপনার বক্তব্য পাই না You আপনি 'কিছু ঘটলে সতর্ক করতে' একজন প্রতিনিধি ব্যবহার করতে পারেন। হতে পারে আপনি এটি করেন নি তবে আপনি পারেন এবং তাই এটি কোনও ইভেন্টের অন্তর্নিহিত সম্পত্তি নয়।
স্টিভ

@ জর্জি কর্ডোবা প্রতিনিধি এবং ইভেন্টের প্রতিনিধি উদাহরণ হলেন একটি সংবাদপত্রের মালিক এবং ইভেন্টগুলি (সাবস্ক্রাইব করুন বা সাবস্ক্রাইব করুন) এবং কিছু লোক সংবাদপত্র কিনে এবং কিছু লোক সংবাদপত্র কিনে না মানে পত্রিকার মালিক প্রত্যেককে সংবাদপত্র কিনতে বাধ্য করতে পারবেন না আমার বক্তব্য ভুল বা ঠিক?
রাহুল_প্যাটিল

37

এখানে উল্লেখ করার জন্য আরও একটি ভাল লিঙ্ক। http://csharpindepth.com/Articles/Chapter2/Events.aspx

সংক্ষেপে, নিবন্ধটি থেকে দূরে সরে যান - ইভেন্টগুলি প্রতিনিধিদের উপর encapsulation হয়।

নিবন্ধ থেকে উদ্ধৃতি:

ধরুন ঘটনা # সি / / নেট তে একটি ধারণা হিসাবে উপস্থিত ছিল না। অন্য শ্রেণি কীভাবে কোনও ইভেন্টের সদস্যতা নেবে? তিনটি বিকল্প:

  1. একটি পাবলিক প্রতিনিধি পরিবর্তনশীল

  2. একটি সম্পত্তি দ্বারা সমর্থিত একটি প্রতিনিধি পরিবর্তনশীল

  3. অ্যাডএক্সএক্সএক্সএন্ডহ্যান্ডলার এবং রিমুভ এক্সএক্সএক্সএইচএন্ডহ্যান্ডলার পদ্ধতি সহ একটি প্রতিনিধি পরিবর্তনশীল able

বিকল্প 1 স্পষ্টতই ভয়ঙ্কর, সমস্ত সাধারণ কারণে আমরা পাবলিক ভেরিয়েবলকে ঘৃণা করি।

বিকল্প 2 সামান্য ভাল, তবে গ্রাহকদের কার্যকরভাবে একে অপরকে ওভাররাইড করার অনুমতি দেয় - এটি কিছুটা লিখতে খুব সহজ হবে IIstance.MyEvent = ইভেন্টহ্যান্ডলার; যা কোনও নতুন ইভেন্ট যুক্ত করার পরিবর্তে কোনও বিদ্যমান ইভেন্ট হ্যান্ডলারকে প্রতিস্থাপন করবে। উপরন্তু, আপনি এখনও বৈশিষ্ট্য লিখতে হবে।

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


সুন্দর এবং সংক্ষিপ্ত ব্যাখ্যা। থ্যাঙ্কস
পাপ

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

যদিও আমি আরও ব্যবহারিক পরামর্শ দিতে চাই, আপনি যদি এমন পরিস্থিতিতে থাকেন যে আপনি কেবল একটি হ্যান্ডলার রয়েছেন তা নিশ্চিত করতে চান, AddXXXHandlerএকটি private Delegateভেরিয়েবলের সাহায্যে আপনার নিজস্ব পদ্ধতি তৈরি করা ভাল বিকল্প হতে পারে। এই ক্ষেত্রে আপনি কোনও হ্যান্ডলার ইতিমধ্যে সেট করা আছে কিনা তা পরীক্ষা করে দেখতে পারেন এবং যথাযথ প্রতিক্রিয়া জানান। আপনার যদি Delegateহ্যান্ডেলটি ধারণ করে রাখা সমস্ত বস্তু সমস্ত হ্যান্ডলারগুলি সাফ করতে সক্ষম হয় ( eventএটি করার কোনও উপায় আপনাকে দেয় না) তবে এটি একটি ভাল সেটআপও হতে পারে ।

7

দ্রষ্টব্য: যদি আপনার সি # 5.0 প্রকাশিত অ্যাক্সেস থাকে তবে দু'জনের মধ্যে পার্থক্যটি আরও ভালভাবে বুঝতে "অধ্যায়গুলি" শিরোনামের 18 অধ্যায়ে "প্রতিনিধিদের সাধারণ ব্যবহারের সীমাবদ্ধতা" পড়ুন।


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

উদাহরণ 1: জন প্রতিনিধি ব্যবহার করে

ধরুন আমার কাছে একটি ড্রপ-ডাউন বক্স সহ একটি উইনফর্মস অ্যাপ রয়েছে। ড্রপ ডাউন একটি আবদ্ধ List<Person>। যেখানে ব্যক্তির আইডি, নাম, ডাকনাম, চুলের রঙের বৈশিষ্ট্য রয়েছে। মূল ফর্মটিতে একটি কাস্টম ব্যবহারকারী নিয়ন্ত্রণ যা সেই ব্যক্তির বৈশিষ্ট্যগুলি দেখায়। যখন কেউ কোনও ব্যক্তিকে নির্বাচিত ব্যক্তির বৈশিষ্ট্যগুলি দেখানোর জন্য ব্যবহারকারী নিয়ন্ত্রণ আপডেটের ড্রপ-ডাউন লেবেলে নির্বাচন করে।

এখানে চিত্র বর্ণনা লিখুন

এখানে যে কিভাবে কাজ করে। আমাদের তিনটি ফাইল রয়েছে যা আমাদের এটি একসাথে রাখতে সহায়তা করে:

  • মধ্যস্থতাবিদরা - স্থিতিশীল শ্রেণি প্রতিনিধিদের ধারণ করে
  • Form1.cs - প্রধান ফর্ম
  • বিশদ বিবরণ। সেগুলি - ব্যবহারকারীর নিয়ন্ত্রণ সমস্ত বিবরণ প্রদর্শন করে

এখানে প্রতিটি ক্লাসের জন্য সম্পর্কিত কোড রয়েছে:

class Mediator
{
    public delegate void PersonChangedDelegate(Person p); //delegate type definition
    public static PersonChangedDelegate PersonChangedDel; //delegate instance. Detail view will "subscribe" to this.
    public static void OnPersonChanged(Person p) //Form1 will call this when the drop-down changes.
    {
        if (PersonChangedDel != null)
        {
            PersonChangedDel(p);
        }
    }
}

এখানে আমাদের ব্যবহারকারীর নিয়ন্ত্রণ:

public partial class DetailView : UserControl
{
    public DetailView()
    {
        InitializeComponent();
        Mediator.PersonChangedDel += DetailView_PersonChanged;
    }

    void DetailView_PersonChanged(Person p)
    {
        BindData(p);
    }

    public void BindData(Person p)
    {
        lblPersonHairColor.Text = p.HairColor;
        lblPersonId.Text = p.IdPerson.ToString();
        lblPersonName.Text = p.Name;
        lblPersonNickName.Text = p.NickName;

    }
}

অবশেষে আমাদের ফর্ম 1 সিএসে নিম্নলিখিত কোড রয়েছে। এখানে আমরা কল করছি অনপারসন চ্যাঞ্জড, যা ডেলিগেটের সদস্যতাযুক্ত কোনও কোডকে কল করে।

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    Mediator.OnPersonChanged((Person)comboBox1.SelectedItem); //Call the mediator's OnPersonChanged method. This will in turn call all the methods assigned (i.e. subscribed to) to the delegate -- in this case `DetailView_PersonChanged`.
}

ঠিক আছে. সুতরাং আপনি কীভাবে ইভেন্টগুলি ব্যবহার না করে এবং কেবলমাত্র প্রতিনিধি ব্যবহার না করেই এই কাজটি পাবেন । আমরা কেবলমাত্র একটি সার্বজনীন প্রতিনিধিকে একটি শ্রেণিতে রেখেছি - আপনি এটি স্ট্যাটিক বা সিঙ্গলটন, বা যা কিছু করতে পারেন। গ্রেট।

বাট, বাট, কিন্তু, আমি কেবল উপরে বর্ণিত যা করতে চাই না। কারণ সরকারী ক্ষেত্রগুলি অনেকের পক্ষে খারাপ , অনেক কারণে। তাহলে আমাদের বিকল্পগুলি কি? জন স্কিট যেমন বর্ণনা করেছেন, এখানে আমাদের বিকল্পগুলি রয়েছে:

  1. একটি পাবলিক ডেলিগেট ভেরিয়েবল (এটি কেবলমাত্র আমরা উপরে করলাম this এটি করবেন না i আমি কেবল আপনাকে খারাপ কারণ কেন এটি খারাপ বলেছি)
  2. প্রতিনিধিটিকে একটি গেট / সেট দিয়ে একটি সম্পত্তিতে রাখুন (এখানে সমস্যাটি হ'ল গ্রাহকরা একে অপরকে ওভাররাইড করতে পারে - সুতরাং আমরা প্রতিনিধিটির কাছে প্রচুর পদ্ধতিতে সাবস্ক্রাইব করতে পারি এবং পরে আমরা ভুলবশত PersonChangedDel = nullঅন্য সমস্ত সাবস্ক্রিপশন মুছে ফেলাতে বলতে পারি The এখানে অন্য সমস্যাটি রয়ে গেছে যেহেতু ব্যবহারকারীদের ডেলিগেটের অ্যাক্সেস রয়েছে তাই তারা অনুরোধের তালিকায় লক্ষ্যগুলি ডেকে আনতে পারে - আমরা কখনই আমাদের ইভেন্টগুলি বাড়ানোর জন্য বহিরাগত ব্যবহারকারীদের অ্যাক্সেস থাকতে চাই না।
  3. অ্যাডএক্সএক্সএক্সএন্ডহ্যান্ডলার এবং রিমুভ এক্সএক্সএক্সএইচএন্ডহ্যান্ডলার পদ্ধতি সহ একটি প্রতিনিধি পরিবর্তনশীল able

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

আসুন দেখুন একই প্রোগ্রামটি দেখতে কেমন, তবে এখন জন প্রতিনিধিদের পরিবর্তে একটি ইভেন্ট ব্যবহার করছি (আমি আমাদের মধ্যস্থতাকে একটি সিঙ্গলটনেও পরিবর্তন করেছি):

উদাহরণ 2: জন প্রতিনিধি পরিবর্তে ইভেন্ট হ্যান্ডলার সহ H

মধ্যস্থ:

class Mediator
{

    private static readonly Mediator _Instance = new Mediator();

    private Mediator() { }

    public static Mediator GetInstance()
    {
        return _Instance;
    }

    public event EventHandler<PersonChangedEventArgs> PersonChanged; //this is just a property we expose to add items to the delegate.

    public void OnPersonChanged(object sender, Person p)
    {
        var personChangedDelegate = PersonChanged as EventHandler<PersonChangedEventArgs>;
        if (personChangedDelegate != null)
        {
            personChangedDelegate(sender, new PersonChangedEventArgs() { Person = p });
        }
    }
}

লক্ষ্য করুন যে আপনি ইভেন্টহ্যান্ডলার এফ 12 করে দিলে এটি আপনাকে সংজ্ঞাটি দেখাবে যে অতিরিক্ত "প্রেরক" অবজেক্টের সাথে জেনেরিক-আইফিড প্রতিনিধি:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

ব্যবহারকারী নিয়ন্ত্রণ:

public partial class DetailView : UserControl
{
    public DetailView()
    {
        InitializeComponent();
        Mediator.GetInstance().PersonChanged += DetailView_PersonChanged;
    }

    void DetailView_PersonChanged(object sender, PersonChangedEventArgs e)
    {
        BindData(e.Person);
    }

    public void BindData(Person p)
    {
        lblPersonHairColor.Text = p.HairColor;
        lblPersonId.Text = p.IdPerson.ToString();
        lblPersonName.Text = p.Name;
        lblPersonNickName.Text = p.NickName;

    }
}

অবশেষে, এখানে ফর্ম 1 কোড কোড রয়েছে:

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
        Mediator.GetInstance().OnPersonChanged(this, (Person)comboBox1.SelectedItem);
}

যেহেতু ইভেন্টহ্যান্ডলার প্যারামিটার হিসাবে চায় এবং ইভেন্টআর্গস, তাই আমি এই ক্লাসটিতে কেবল একটি একক সম্পত্তি রেখে তৈরি করেছি:

class PersonChangedEventArgs
{
    public Person Person { get; set; }
}

আশা করি যে এটি আমাদের কেন অনুষ্ঠানগুলি করে এবং সেগুলি কীভাবে আলাদা সেগুলি সম্পর্কে কিছুটা দেখায় - তবে কার্যত একইভাবে - প্রতিনিধি হিসাবে।


যদিও আমি এই পোস্টে সমস্ত ভাল কাজের প্রশংসা করেছি এবং এর বেশিরভাগটি পড়তে আমি আনন্দিত হয়েছি, তবুও আমি অনুভব করি যে একটি বিষয় সমাধান করা হয়নি - The other problem that remains here is that since the users have access to the delegate, they can invoke the targets in the invocation list -- we don't want external users having access to when to raise our events। এর সর্বশেষতম সংস্করণে Mediator, আপনি OnPersonChangeযখনই সিঙ্গলটনের রেফারেন্স পাবেন তখনও আপনি কল করতে পারবেন । হতে পারে আপনার উল্লেখ করা উচিত যে Mediatorপদ্ধতির সেই নির্দিষ্ট আচরণটি প্রতিরোধ করা হয় না, এবং ইভেন্ট বাসের কাছাকাছি।
Ivaylo স্লাভভ

6

আপনি ইন্টারফেসের ঘোষণায় ইভেন্টগুলিও ব্যবহার করতে পারেন, প্রতিনিধিদের জন্য নয় so


2
@ সুরফেন ইন্টারফেসে ইভেন্টগুলি থাকতে পারে, তবে প্রতিনিধিরা থাকতে পারে না।
আলেকজান্দ্রার নিকিতিন

1
আপনি ঠিক কি বোঝাতে চেয়েছেন? আপনি Action a { get; set; }একটি ইন্টারফেস সংজ্ঞা ভিতরে থাকতে পারে ।
চিয়েল দশ ব্রিনকে

6

ইভেন্ট এবং প্রতিনিধিদের মধ্যে কি দুর্দান্ত ভুল বোঝাবুঝি !!! একটি প্রতিনিধি একটি টিওয়াইপি (যেমন একটি class, বা একটি কর interface) নির্দিষ্ট করে, অন্যদিকে ইভেন্টটি কেবল এক ধরণের সদস্য (যেমন ক্ষেত্র, বৈশিষ্ট্য ইত্যাদি)। এবং অন্যান্য সদস্যের মতোই কোনও ইভেন্টেরও একটি প্রকার থাকে। তবুও, কোনও ইভেন্টের ক্ষেত্রে, অনুষ্ঠানের ধরণটি অবশ্যই কোনও প্রতিনিধি দ্বারা নির্দিষ্ট করা আবশ্যক। উদাহরণস্বরূপ, আপনি কোনও ইন্টারফেস দ্বারা সংজ্ঞায়িত কোনও ধরণের ইভেন্ট ঘোষণা করতে পারবেন না।

সমাপ্তি, আমরা নিম্নলিখিত পর্যবেক্ষণ করতে পারি : একটি প্রতিনিধি দ্বারা সংঘবদ্ধ হওয়া আবশ্যক ইভেন্টের ধরণ । এটা এমন এক ঘটনা এবং একটি প্রতিনিধি মধ্যে মূল সম্পর্ক নেই এবং বিভাগে বর্ণনা করা হয়েছে II.18 সংজ্ঞা ঘটনা এর ECMA-335 (CLI) দ্বারা পার্টিশন আমি ষষ্ঠ থেকে :

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

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


4

। নেট এর একটি ইভেন্ট হ'ল একটি অ্যাড পদ্ধতি এবং একটি সরান পদ্ধতির একটি মনোনীত সংমিশ্রণ, উভয়ই কিছু নির্দিষ্ট ধরণের প্রতিনিধি আশা করে। সি # এবং vb.net উভয়ই অ্যাড এবং রিমুথ পদ্ধতিগুলির জন্য কোড স্বয়ংক্রিয়ভাবে উত্পন্ন করতে পারে যা ইভেন্টের সাবস্ক্রিপশন ধরে রাখার জন্য কোনও প্রতিনিধিকে সংজ্ঞায়িত করবে এবং সেই সাবস্ক্রিপশন প্রতিনিধি থেকে / পাসের প্রতিনিধিটিকে যুক্ত / সরিয়ে ফেলবে। VB.net এছাড়াও সাবস্ক্রিপশন তালিকার অনুরোধ করতে কোডটি (RaiseEvent বিবৃতি সহ) স্বয়ংক্রিয়ভাবে উত্পন্ন করবে যদি তা কেবল খালি না থাকে; কোনও কারণে, সি # উত্তরোত্তর উত্পন্ন করে না।

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


3

সহজ পদ্ধতিতে ইভেন্ট সম্পর্কে সংজ্ঞা দেওয়া:

ইভেন্ট দুটি বিধিনিষেধ সহ একটি প্রতিনিধিদের জন্য একটি রেফারেন্স

  1. সরাসরি ডাকা যাবে না
  2. সরাসরি মূল্য বরাদ্দ করা যায় না (যেমন ইভেন্টবজ = ডেলিগেটমেডোদ)

দুটির উপরে প্রতিনিধিদের জন্য দুর্বল পয়েন্টগুলি রয়েছে এবং এটি ইভেন্টে সম্বোধন করা হয়। ফিডলারের পার্থক্য দেখানোর জন্য কোডের সম্পূর্ণ নমুনাটি এখানে https://dotnetfiddle.net/5iR3fB

ইভেন্ট এবং ডেলিগেট এবং ক্লায়েন্ট কোডের মধ্যে মন্তব্যটি টগল করুন যা পার্থক্যটি বোঝার জন্য ডেলিগেট করতে মানগুলিকে অনুরোধ করে / নির্ধারণ করে

এখানে ইনলাইন কোড।

 /*
This is working program in Visual Studio.  It is not running in fiddler because of infinite loop in code.
This code demonstrates the difference between event and delegate
        Event is an delegate reference with two restrictions for increased protection

            1. Cannot be invoked directly
            2. Cannot assign value to delegate reference directly

Toggle between Event vs Delegate in the code by commenting/un commenting the relevant lines
*/

public class RoomTemperatureController
{
    private int _roomTemperature = 25;//Default/Starting room Temperature
    private bool _isAirConditionTurnedOn = false;//Default AC is Off
    private bool _isHeatTurnedOn = false;//Default Heat is Off
    private bool _tempSimulator = false;
    public  delegate void OnRoomTemperatureChange(int roomTemperature); //OnRoomTemperatureChange is a type of Delegate (Check next line for proof)
    // public  OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above), 
    public  event OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above), 

    public RoomTemperatureController()
    {
        WhenRoomTemperatureChange += InternalRoomTemperatuerHandler;
    }
    private void InternalRoomTemperatuerHandler(int roomTemp)
    {
        System.Console.WriteLine("Internal Room Temperature Handler - Mandatory to handle/ Should not be removed by external consumer of ths class: Note, if it is delegate this can be removed, if event cannot be removed");
    }

    //User cannot directly asign values to delegate (e.g. roomTempControllerObj.OnRoomTemperatureChange = delegateMethod (System will throw error)
    public bool TurnRoomTeperatureSimulator
    {
        set
        {
            _tempSimulator = value;
            if (value)
            {
                SimulateRoomTemperature(); //Turn on Simulator              
            }
        }
        get { return _tempSimulator; }
    }
    public void TurnAirCondition(bool val)
    {
        _isAirConditionTurnedOn = val;
        _isHeatTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
        System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
        System.Console.WriteLine("Heat :" + _isHeatTurnedOn);

    }
    public void TurnHeat(bool val)
    {
        _isHeatTurnedOn = val;
        _isAirConditionTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
        System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
        System.Console.WriteLine("Heat :" + _isHeatTurnedOn);

    }

    public async void SimulateRoomTemperature()
    {
        while (_tempSimulator)
        {
            if (_isAirConditionTurnedOn)
                _roomTemperature--;//Decrease Room Temperature if AC is turned On
            if (_isHeatTurnedOn)
                _roomTemperature++;//Decrease Room Temperature if AC is turned On
            System.Console.WriteLine("Temperature :" + _roomTemperature);
            if (WhenRoomTemperatureChange != null)
                WhenRoomTemperatureChange(_roomTemperature);
            System.Threading.Thread.Sleep(500);//Every second Temperature changes based on AC/Heat Status
        }
    }

}

public class MySweetHome
{
    RoomTemperatureController roomController = null;
    public MySweetHome()
    {
        roomController = new RoomTemperatureController();
        roomController.WhenRoomTemperatureChange += TurnHeatOrACBasedOnTemp;
        //roomController.WhenRoomTemperatureChange = null; //Setting NULL to delegate reference is possible where as for Event it is not possible.
        //roomController.WhenRoomTemperatureChange.DynamicInvoke();//Dynamic Invoke is possible for Delgate and not possible with Event
        roomController.SimulateRoomTemperature();
        System.Threading.Thread.Sleep(5000);
        roomController.TurnAirCondition (true);
        roomController.TurnRoomTeperatureSimulator = true;

    }
    public void TurnHeatOrACBasedOnTemp(int temp)
    {
        if (temp >= 30)
            roomController.TurnAirCondition(true);
        if (temp <= 15)
            roomController.TurnHeat(true);

    }
    public static void Main(string []args)
    {
        MySweetHome home = new MySweetHome();
    }


}

2

ডেলিগেট হ'ল টাইপ-সেফ ফাংশন পয়েন্টার। ইভেন্ট প্রতিনিধি ব্যবহার করে প্রকাশক-গ্রাহক ডিজাইন প্যাটার্নের একটি বাস্তবায়ন।


0

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

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

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