আমি কীভাবে সি # তে ইভেন্টের সদস্যতাগুলি সাফ করতে পারি?


141

নিম্নলিখিত সি # বর্গ নিন:

c1 {
 event EventHandler someEvent;
}

যদি সাবস্ক্রিপশন অনেক আছে c1এর someEventঘটনা ও আমি তাদের সব পরিষ্কার করতে চাই, সবচেয়ে ভালো উপায় এই অর্জন করার কি? এছাড়াও বিবেচনা করুন যে এই ইভেন্টের সদস্যতাগুলি লাম্বদা / বেনাম প্রতিনিধি হতে পারে / হতে পারে।

বর্তমানে আমার সমাধানটি হ'ল কোনও ResetSubscriptions()পদ্ধতি যুক্ত করে c1সেটগুলি someEventবাতিল করে দেয়। আমি জানি না এর কোনও অদৃশ্য পরিণতি আছে কিনা।

উত্তর:


181

শ্রেণীর মধ্যে থেকে, আপনি (লুকানো) ভেরিয়েবলটি নালায় সেট করতে পারেন। একটি নাল রেফারেন্স হ'ল কার্যকরভাবে খালি প্রার্থনা তালিকার উপস্থাপনের প্রমিত উপায়।

শ্রেণীর বাইরে থেকে, আপনি এটি করতে পারবেন না - ইভেন্টগুলি মূলত "সাবস্ক্রাইব" এবং "আনসাবস্ক্রাইব" প্রকাশ করে এবং এটিই।

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

আরও তথ্যের জন্য ইভেন্ট এবং প্রতিনিধিদের বিষয়ে আমার নিবন্ধটি দেখুন ।


3
যদি আপনি একগুঁয়ে হন, তবে আপনি প্রতিবিম্বের মাধ্যমে এটি পরিষ্কার করতে বাধ্য করতে পারেন। স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / 91778/ … দেখুন ।
ব্রায়ান

1
@ ব্রায়ান: এটি বাস্তবায়নের উপর নির্ভর করে। এটি যদি কেবল ক্ষেত্রের মতো ইভেন্ট বা একটি হয় তবে EventHandlerListআপনি সক্ষম হতে পারেন। আপনাকে এই দুটি কেসটি স্বীকৃতি দিতে হবে - এবং এর মধ্যে আরও কয়েকটি বাস্তবায়ন হতে পারে।
জন স্কিটি

@ জোশুয়া: না, এটি নথের মান রাখতে ভেরিয়েবলকে সেট করবে। আমি একমত যে চলক বলা হবে না hidden
জন স্কিটি

@ জোনস্কিট আমি যা বলেছিলাম (তা ভেবে) এটি যেভাবে লেখা হয়েছিল তা আমাকে 5 মিনিটের জন্য বিভ্রান্ত করে।

@ জোশুয়া লামুসগা: আচ্ছা আপনি বলেছিলেন যে এটি একটি অনুরোধের তালিকা সাফ করবে, যা বিদ্যমান অবজেক্টটি সংশোধন করার মতো শোনাচ্ছে।
জন স্কিটি

34

সি 1 তে এমন একটি পদ্ধতি যুক্ত করুন যা 'সামান্য' সেট করে ফেলবে।

public class c1
{
    event EventHandler someEvent;
    public ResetSubscriptions() => someEvent = null;    
}

সেই আচরণই আমি দেখছি। আমি আমার প্রশ্নে যেমন বলেছিলাম, আমি জানি না আমি কিছু উপেক্ষা করছি কিনা।
প্রোগ্রামার

8
class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() => someEvent = delegate { };
}

নাল রেফ ব্যতিক্রম এড়ানোর delegate { }চেয়ে ব্যবহার করা ভাল null


2
কেন? আপনি কি এই উত্তরটি প্রসারিত করতে পারেন?
এস বুদা

1
@ এসবুদা কারণ এটি যদি নাল হয় তবে আপনি একটি নাল রেফার পাবেন। এটি একটি List.Clear()বনাম ব্যবহার মত myList = null
অস্টিন ডাব্লু ব্রায়ান

6

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


6

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

সংক্ষেপে, পৃষ্ঠা পৃষ্ঠা 125 - সি # 4.0 বইটি দেখুন।

এখানে কেউ কেউ Delegate.RemoveAllপদ্ধতি ব্যবহারের প্রস্তাব দিয়েছিলেন । আপনি যদি এটি ব্যবহার করেন তবে নমুনা কোডটি নীচের ফর্মটি অনুসরণ করতে পারে। তবে এটি আসলেই বোকা। কেন শুধু ফাংশন SomeEvent=nullভিতরে না ClearSubscribers()?

public void ClearSubscribers ()
{
   SomeEvent = (EventHandler) Delegate.RemoveAll(SomeEvent, SomeEvent);
   // Then you will find SomeEvent is set to null.
}

5

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


6
আমি বিশ্বাস করি না এটি ল্যাম্বডা অভিব্যক্তি বা বেনামে প্রতিনিধিদের সাথে কাজ করবে।
প্রোগ্রামার

3

ধারণাগত বর্ধিত বিরক্তিকর মন্তব্য।

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

const
  WM_Paint = 998;  // <-- "question" can be done by several talkers
  WM_Clear = 546;

type
  MyWindowClass = class(Window)
    procedure NotEventHandlerMethod_1;
    procedure NotEventHandlerMethod_17;

    procedure DoPaintEventHandler; message WM_Paint; // <-- "answer" by this listener
    procedure DoClearEventHandler; message WM_Clear;
  end;

এবং, এই "বার্তাটির" প্রতিক্রিয়া জানানোর জন্য, "ইভেন্ট হ্যান্ডলার" প্রতিক্রিয়া জানায়, একক প্রতিনিধি বা একাধিক প্রতিনিধি কিনা।

সংক্ষিপ্তসার: "ইভেন্ট" হ'ল "প্রশ্ন", "ইভেন্ট হ্যান্ডলার (গুলি)" এর উত্তর (গুলি)।


1

এটি আমার সমাধান:

public class Foo : IDisposable
{
    private event EventHandler _statusChanged;
    public event EventHandler StatusChanged
    {
        add
        {
            _statusChanged += value;
        }
        remove
        {
            _statusChanged -= value;
        }
    }

    public void Dispose()
    {
        _statusChanged = null;
    }
}

অনুরোধ তালিকার সমস্ত সদস্যের সদস্যতা ত্যাগ Dispose()করতে আপনাকে কল করতে বা using(new Foo()){/*...*/}প্যাটার্ন ব্যবহার করতে হবে।


0

সমস্ত ইভেন্ট সরান, ধরে নিন ইভেন্টটি একটি "ক্রিয়া" প্রকার:

Delegate[] dary = TermCheckScore.GetInvocationList();

if ( dary != null )
{
    foreach ( Delegate del in dary )
    {
        TermCheckScore -= ( Action ) del;
    }
}

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

-1

ম্যানুয়ালি কলব্যাকগুলি যুক্ত করা এবং মুছে ফেলার পরিবর্তে এবং সর্বত্র সর্বত্র ঘোষিত প্রতিনিধি প্রকারের একত্রিত হওয়া:

// The hard way
public delegate void ObjectCallback(ObjectType broadcaster);

public class Object
{
    public event ObjectCallback m_ObjectCallback;
    
    void SetupListener()
    {
        ObjectCallback callback = null;
        callback = (ObjectType broadcaster) =>
        {
            // one time logic here
            broadcaster.m_ObjectCallback -= callback;
        };
        m_ObjectCallback += callback;

    }
    
    void BroadcastEvent()
    {
        m_ObjectCallback?.Invoke(this);
    }
}

আপনি এই জেনেরিক পদ্ধতির চেষ্টা করতে পারেন:

public class Object
{
    public Broadcast<Object> m_EventToBroadcast = new Broadcast<Object>();

    void SetupListener()
    {
        m_EventToBroadcast.SubscribeOnce((ObjectType broadcaster) => {
            // one time logic here
        });
    }

    ~Object()
    {
        m_EventToBroadcast.Dispose();
        m_EventToBroadcast = null;
    }

    void BroadcastEvent()
    {
        m_EventToBroadcast.Broadcast(this);
    }
}


public delegate void ObjectDelegate<T>(T broadcaster);
public class Broadcast<T> : IDisposable
{
    private event ObjectDelegate<T> m_Event;
    private List<ObjectDelegate<T>> m_SingleSubscribers = new List<ObjectDelegate<T>>();

    ~Broadcast()
    {
        Dispose();
    }

    public void Dispose()
    {
        Clear();
        System.GC.SuppressFinalize(this);
    }

    public void Clear()
    {
        m_SingleSubscribers.Clear();
        m_Event = delegate { };
    }

    // add a one shot to this delegate that is removed after first broadcast
    public void SubscribeOnce(ObjectDelegate<T> del)
    {
        m_Event += del;
        m_SingleSubscribers.Add(del);
    }

    // add a recurring delegate that gets called each time
    public void Subscribe(ObjectDelegate<T> del)
    {
        m_Event += del;
    }

    public void Unsubscribe(ObjectDelegate<T> del)
    {
        m_Event -= del;
    }

    public void Broadcast(T broadcaster)
    {
        m_Event?.Invoke(broadcaster);
        for (int i = 0; i < m_SingleSubscribers.Count; ++i)
        {
            Unsubscribe(m_SingleSubscribers[i]);
        }
        m_SingleSubscribers.Clear();
    }
}

আপনি কি দয়া করে আপনার প্রশ্নটি ফর্ম্যাট করতে এবং বাম দিকের সমস্ত সাদা স্থান সরিয়ে ফেলতে পারেন? আপনি যখন কোনও আইডিই থেকে অনুলিপি করুন এবং পেস্ট করবেন তখন এটি ঘটতে পারে
অস্টিন ডাব্লু ব্রায়ান

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