সি # তে বেনামে পদ্ধতিটি সাবস্ক্রাইব করুন


222

কোনও ইভেন্ট থেকে কোনও বেনামী পদ্ধতিটি বাতিল করা সম্ভব?

যদি আমি এই জাতীয় কোনও ইভেন্টের সাবস্ক্রাইব করি:

void MyMethod()
{
    Console.WriteLine("I did it!");
}

MyEvent += MyMethod;

আমি এটির মতো সাবস্ক্রাইব করতে পারি:

MyEvent -= MyMethod;

তবে আমি যদি একটি বেনাম পদ্ধতি ব্যবহার করে সাবস্ক্রাইব করি:

MyEvent += delegate(){Console.WriteLine("I did it!");};

এই অনামী পদ্ধতিটি কি সাবস্ক্রাইব করা সম্ভব? যদি তাই হয়, কিভাবে?


4
হিসাবে কেন : যদি আপনি এই ব্যবহার করতে পারবেন না stackoverflow.com/a/25564492/23354
মার্ক Gravell

উত্তর:


230
Action myDelegate = delegate(){Console.WriteLine("I did it!");};

MyEvent += myDelegate;


// .... later

MyEvent -= myDelegate;

চারপাশে প্রতিনিধি একটি রেফারেন্স রাখুন।


141

একটি কৌশল হ'ল বেনাম পদ্ধতিটি ধরে রাখার জন্য একটি ভেরিয়েবল ঘোষণা করা যা পরে বেনামি পদ্ধতিতেই পাওয়া যায়। এটি আমার পক্ষে কাজ করেছিল কারণ ইভেন্টটি পরিচালনার পরে কাঙ্ক্ষিত আচরণটি সাবস্ক্রাইব করা ছিল।

উদাহরণ:

MyEventHandler foo = null;
foo = delegate(object s, MyEventArgs ev)
    {
        Console.WriteLine("I did it!");
        MyEvent -= foo;
    };
MyEvent += foo;

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

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

2
আমার যা প্রয়োজন তা-ই! আমি = নাল অনুপস্থিত ছিল। (MyEventHandler foo = প্রতিনিধি {... MyEvent- = foo;}; MyEvent + = foo; কাজ করেনি ...)
TDaver

আপনি যদি এটিকে অ্যারে হিসাবে ঘোষণা করেন তবে পুনঃভাগ 6.1 অভিযোগ করবে না। কিছুটা অদ্ভুত বলে মনে হচ্ছে, তবে আমি অনুলিপিভাবে আমার এই সরঞ্জামগুলিতে আমার সরঞ্জামগুলিতে বিশ্বাস রাখতে চলেছি: MyEventHandler [] foo = {নাল}; foo [0] = ... {... আমার ঘটনা - = ফু [0]; }; MyEvent + = foo [0];
মাইক পোস্ট

21

স্মৃতি থেকে, স্পেসিফিকেশন স্পষ্টভাবে আচরণের গ্যারান্টি দেয় না যখন এটি বেনাম পদ্ধতিগুলির সাথে তৈরি প্রতিনিধিদের সমতার ক্ষেত্রে আসে equiv

আপনার যদি সাবস্ক্রাইব করতে হয়, আপনার হয় "সাধারণ" পদ্ধতিটি ব্যবহার করা উচিত বা অন্য কোথাও প্রতিনিধিটিকে ধরে রাখা উচিত যাতে আপনি ঠিক একই প্রতিনিধির সাথে সাবস্ক্রাইব করতে পারেন যে আপনি সাবস্ক্রাইব করেছেন।


আমি জোন, তুমি কী করছ? আমি বুঝতে পারছি না। "জে সি" দ্বারা উদ্ঘাটিত সমাধান কি সঠিকভাবে কাজ করবে না?
এরিক ওয়েললেট

@ এরিক অয়েললেট: এই উত্তরটি মূলত "অন্য কোথাও প্রতিনিধি বজায় রাখা যাতে আপনি একইরকম প্রতিনিধি সাবস্ক্রাইব করার জন্য সাবস্ক্রাইব করতে পারেন" এর একটি বাস্তবায়ন।
জন স্কিটি

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

1
আমি খুঁজে পেয়েছি: এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms366768.aspx তবে তারা বেনামে ব্যবহার না করার পরামর্শ দেয় তবে তারা বলে না যে এখানে কোন বড় সমস্যা আছে?
এরিক ওয়েললেট

আমি এটি পেয়েছি ... অনেক অনেক ধন্যবাদ (মাইকেল ব্লোমের উত্তর দেখুন): social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/…
এরিক ওয়েললেট

16

3.0 এ সংক্ষিপ্ত করা যেতে পারে:

MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;

15

যেহেতু সি # .0.০ স্থানীয় ফাংশন বৈশিষ্ট্য প্রকাশিত হয়েছে, জে সি দ্বারা প্রস্তাবিত পদ্ধতিটি খুব ঝরঝরে হয়ে যায়।

void foo(object s, MyEventArgs ev)
{
    Console.WriteLine("I did it!");
    MyEvent -= foo;
};
MyEvent += foo;

সুতরাং, সত্যি বলতে, আপনার এখানে ভেরিয়েবল হিসাবে বেনামে ফাংশন নেই। তবে আমি মনে করি এটি আপনার ক্ষেত্রে এটির ব্যবহারের অনুপ্রেরণা স্থানীয় ফাংশনগুলিতে প্রয়োগ করা যেতে পারে।


1
পাঠযোগ্যতা আরও উন্নত করতে, আপনি MyEvent + = foo স্থানান্তর করতে পারেন; foo ঘোষণার আগে হতে লাইন।
মার্ক ঝুকভস্কি

9

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

public class MyClass 
{
  public event EventHandler MyEvent;

  public IEnumerable<EventHandler> GetMyEventHandlers()  
  {  
      return from d in MyEvent.GetInvocationList()  
             select (EventHandler)d;  
  }  
}

সুতরাং আপনি মাইক্লাসের বাইরে থেকে সম্পূর্ণ অনুরোধের তালিকাটি অ্যাক্সেস করতে পারেন এবং আপনার যে কোনও হ্যান্ডলারটি চান তা বাতিল করতে পারেন। এই ক্ষেত্রে:

myClass.MyEvent -= myClass.GetMyEventHandlers().Last();

আমি এখানে এই কৌশল সম্পর্কে একটি সম্পূর্ণ পোস্ট লিখেছি ।


2
এর অর্থ কি এই ঘটনাক্রমে ঘটনাটি যদি তারা আমার পরে সাবস্ক্রাইব করে তবে আমি ঘটনাক্রমে কোনও আলাদা উদাহরণ (অর্থাৎ আমাকে নয়) আনসাবস্ক্রাইব করতে পারি?
ডুম্বলডেড

@ ডাম্বলড্যাড অবশ্যই এটি সর্বশেষে নিবন্ধিত সর্বশেষ নিবন্ধন করবে। আপনি যদি কোনও নির্দিষ্ট বেনামী প্রতিনিধিকে গতিশীলভাবে সদস্যতা ছেড়ে দিতে চান, তবে আপনাকে এটি কোনওভাবে সনাক্ত করতে হবে। আমি তখন একটি রেফারেন্স রাখার পরামর্শ দেব :)
লাক্যলিকি

এটি বেশ দুর্দান্ত, আপনি কী করছেন, তবে আমি এমন একটি ক্ষেত্রে কল্পনা করতে পারি না যেখানে এটি কার্যকর হতে পারে। তবে আমি আসলেই ওপি'র প্রশ্নের সমাধান করতে পারি না। -> +1 আইএমএইচও, পরে বেনামে নিবন্ধভুক্ত করা উচিত তবে তাদের অনামী প্রতিনিধিদের ব্যবহার করা উচিত নয়। এগুলি রাখা বোকামি -> আরও ভাল ব্যবহারের পদ্ধতি। আমন্ত্রণ তালিকায় কেবলমাত্র কিছু প্রতিনিধি সরিয়ে নেওয়া বেশ এলোমেলো এবং অকেজো। আমি ভুল হলে শুধরে. :)
লাকিলিকি

6

খোঁড়া পদ্ধতির ধরনের:

public class SomeClass
{
  private readonly IList<Action> _eventList = new List<Action>();

  ...

  public event Action OnDoSomething
  {
    add {
      _eventList.Add(value);
    }
    remove {
      _eventList.Remove(value);
    }
  }
}
  1. ইভেন্ট অ্যাড / অপসারণ পদ্ধতিগুলিকে ওভাররাইড করুন।
  2. Event ইভেন্ট হ্যান্ডলারের একটি তালিকা রাখুন।
  3. যখন প্রয়োজন হয়, এগুলি সমস্ত সাফ করুন এবং অন্যদের পুনরায় যুক্ত করুন।

এটি কাজ না করে বা সবচেয়ে কার্যকর পদ্ধতি হতে পারে, তবে কাজটি করা উচিত।


14
আপনি যদি মনে করেন এটি খোঁড়া, পোস্ট করবেন না।
জেরি নিকসন

2

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


2

একটি সহজ সমাধান:

কেবল পরামিতি হিসাবে ইভেন্ট হ্যান্ডেল ভেরিয়েবলটি পাস করুন। ইভেন্টটি যদি আপনার ক্ষেত্রে থাকে যে আপনি মাল্টিথ্রেডিংয়ের কারণে আসল তৈরি চলকটি অ্যাক্সেস করতে পারবেন না, আপনি এটি ব্যবহার করতে পারেন:

MyEventHandler foo = null;
foo = (s, ev, mehi) => MyMethod(s, ev, foo);
MyEvent += foo;

void MyMethod(object s, MyEventArgs ev, MyEventHandler myEventHandlerInstance)
{
    MyEvent -= myEventHandlerInstance;
    Console.WriteLine("I did it!");
}

যদি মাইইভেন্ট দু'বার আহ্বান করা হয় তবে আগে MyEvent -= myEventHandlerInstance;রান করা হবে? যদি এটি সম্ভব হয় তবে আপনার একটি ত্রুটি আছে। তবে বিষয়টি নিশ্চিত কিনা তা আমি নিশ্চিত নই।
লাকিলিকি

0

আপনি যদি এই প্রতিনিধিটির সাথে কোনও বস্তুর উল্লেখ করতে চান তবে আপনি ডেলিগেট ব্যবহার করতে পারেন D


0

সাবস্ক্রাইব করা ইভেন্ট হ্যান্ডলার সম্পর্কে যদি সর্বোত্তম উপায়টি হয় তবে এটি একটি অভিধান ব্যবহার করে অর্জন করা যেতে পারে।

এই উদাহরণে, আমাকে ডেটাগ্রিডভিউজের সেটগুলির জন্য মার্জক্লাম প্যারামিটার অন্তর্ভুক্ত করতে একটি বেনামী পদ্ধতি ব্যবহার করতে হবে।

সত্য হিসাবে সেট করা সক্ষম প্যারামিটারের সাথে মার্জক্লোম পদ্ধতিটি ব্যবহার করা ইভেন্টটিকে মিথ্যা অক্ষম করে এটি সক্ষম করে।

static Dictionary<DataGridView, PaintEventHandler> subscriptions = new Dictionary<DataGridView, PaintEventHandler>();

public static void MergeColumns(this DataGridView dg, bool enable, params ColumnGroup[] mergedColumns) {

    if(enable) {
        subscriptions[dg] = (s, e) => Dg_Paint(s, e, mergedColumns);
        dg.Paint += subscriptions[dg];
    }
    else {
        if(subscriptions.ContainsKey(dg)) {
            dg.Paint -= subscriptions[dg];
            subscriptions.Remove(dg);
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.