আপনার ক্ষেত্রে, সবকিছু ঠিক আছে। এটি অবজেক্ট যা ইভেন্টগুলি প্রকাশ করে যা ইভেন্ট হ্যান্ডলারের লক্ষ্যগুলিকে লাইভ রাখে । সুতরাং আমি যদি:
publisher.SomeEvent += target.DoSomething;
তারপরে publisher
একটি রেফারেন্স রয়েছে target
তবে অন্যভাবে নয়।
আপনার ক্ষেত্রে, প্রকাশক আবর্জনা সংগ্রহের জন্য যোগ্য হতে চলেছেন (ধরে নেওয়া যায় এর সাথে অন্য কোনও উল্লেখ নেই) সুতরাং এটি ইভেন্ট হ্যান্ডলার লক্ষ্যগুলির একটি রেফারেন্স পেয়েছে তা অপ্রাসঙ্গিক।
জটিল কেসটি যখন প্রকাশক দীর্ঘায়ু থাকেন তবে গ্রাহকরা হতে চান না - সেই ক্ষেত্রে আপনাকে হ্যান্ডলারের সদস্যতা বাতিল করতে হবে। উদাহরণস্বরূপ, ধরুন আপনার কাছে কিছু ডেটা ট্রান্সফার পরিষেবা রয়েছে যা আপনাকে ব্যান্ডউইথ পরিবর্তন সম্পর্কে অ্যাসিনক্রোনাস বিজ্ঞপ্তিগুলি সাবস্ক্রাইব করতে দেয় এবং স্থানান্তর পরিষেবা অবজেক্টটি দীর্ঘকালীন। আমরা যদি এটি করি:
BandwidthUI ui = new BandwidthUI();
transferService.BandwidthChanged += ui.HandleBandwidthChange;
// Suppose this blocks until the transfer is complete
transferService.Transfer(source, destination);
// We now have to unsusbcribe from the event
transferService.BandwidthChanged -= ui.HandleBandwidthChange;
(আপনি ইভেন্ট হ্যান্ডলারটি ফাঁস করবেন না তা নিশ্চিত করার জন্য আপনি আসলে একটি শেষ অবধি ব্যবহার করতে চান we) আমরা যদি সাবস্ক্রাইব না করি BandwidthUI
তবে ট্রান্সফার পরিষেবাটি অন্তত দীর্ঘকাল বেঁচে থাকবে।
ব্যক্তিগতভাবে আমি খুব কমই এটিকে ঘুরে আসি - সাধারণত আমি যদি কোনও ইভেন্টের সাবস্ক্রাইব করি তবে সেই ইভেন্টের লক্ষ্যটি অন্ততপক্ষে প্রকাশক হিসাবে বেঁচে থাকে - উদাহরণস্বরূপ, একটি ফর্ম যতক্ষণ থাকবে তাতে যতক্ষণ বাটন থাকবে ততক্ষণ দীর্ঘস্থায়ী থাকবে। এই সম্ভাব্য সমস্যাটি সম্পর্কে জানার পক্ষে মূল্যবান, তবে আমি মনে করি কিছু লোকেরা যখন তাদের প্রয়োজন না হয় তখন এটি নিয়ে উদ্বিগ্ন হয়, কারণ তারা জানে না যে রেফারেন্সগুলি প্রায় কোন পথে যায়।
সম্পাদনা: এটি জোনাথন ডিকিনসনের মন্তব্যের জবাব দেওয়ার জন্য। প্রথমত, ডেলিগেট.একুয়ালস (অবজেক্ট) এর জন্য দস্তাবেজগুলি দেখুন যা স্পষ্টভাবে সাম্যের আচরণ দেয়।
দ্বিতীয়ত, আনসস্ক্রিপশন কাজ করার জন্য এখানে একটি ছোট কিন্তু সম্পূর্ণ প্রোগ্রামটি রয়েছে:
using System;
public class Publisher
{
public event EventHandler Foo;
public void RaiseFoo()
{
Console.WriteLine("Raising Foo");
EventHandler handler = Foo;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
else
{
Console.WriteLine("No handlers");
}
}
}
public class Subscriber
{
public void FooHandler(object sender, EventArgs e)
{
Console.WriteLine("Subscriber.FooHandler()");
}
}
public class Test
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.Foo += subscriber.FooHandler;
publisher.RaiseFoo();
publisher.Foo -= subscriber.FooHandler;
publisher.RaiseFoo();
}
}
ফলাফল:
Raising Foo
Subscriber.FooHandler()
Raising Foo
No handlers
(মনো এবং .NET 3.5SP1 এ পরীক্ষিত))
আরও সম্পাদনা:
এটি প্রমাণ করার জন্য যে কোনও ইভেন্ট প্রকাশক সংগ্রহ করা যেতে পারে যখন সেখানে কোনও গ্রাহকের উল্লেখ রয়েছে।
using System;
public class Publisher
{
~Publisher()
{
Console.WriteLine("~Publisher");
Console.WriteLine("Foo==null ? {0}", Foo == null);
}
public event EventHandler Foo;
}
public class Subscriber
{
~Subscriber()
{
Console.WriteLine("~Subscriber");
}
public void FooHandler(object sender, EventArgs e) {}
}
public class Test
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
publisher.Foo += subscriber.FooHandler;
Console.WriteLine("No more refs to publisher, "
+ "but subscriber is alive");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("End of Main method. Subscriber is about to "
+ "become eligible for collection");
GC.KeepAlive(subscriber);
}
}
ফলাফল (.NET 3.5SP1 এ; মনো এখানে কিছুটা অদ্ভুত আচরণ করবে বলে মনে হচ্ছে that কিছু সময়ের মধ্যে এটি খতিয়ে দেখবে):
No more refs to publisher, but subscriber is alive
~Publisher
Foo==null ? False
End of Main method. Subscriber is about to become eligible for collection
~Subscriber