Jump to content
  • Advertisement
Sign in to follow this  
PixelPants

[.net] Single-cast delegate?

This topic is 2645 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

All this time I thought delegates were single-cast, and that events were essentially a list of delegates (allowing for multi-cast). Well, today I learned that you could use the += operator on a delegate!

As can be expected, this knocked me off my chair... :blink:

I dug into the theory a bit, and found that the 'delegate' keyword essentially used 'System.MulticastDelegate', and that 'System.Delegate' was a single-cast delegate.

System.Object
->System.Delegate
->->System.MulticastDelegate

However, according to MSDN, I'm not allowed to use System.Delegate (it's a "special class" to be used only by the compiler). So what's the standard way to get a single-cast delegate?

Share this post


Link to post
Share on other sites
Advertisement

All this time I thought delegates were single-cast, and that events were essentially a list of delegates (allowing for multi-cast). Well, today I learned that you could use the += operator on a delegate!

As can be expected, this knocked me off my chair... :blink:

I dug into the theory a bit, and found that the 'delegate' keyword essentially used 'System.MulticastDelegate', and that 'System.Delegate' was a single-cast delegate.

System.Object
->System.Delegate
->->System.MulticastDelegate

However, according to MSDN, I'm not allowed to use System.Delegate (it's a "special class" to be used only by the compiler). So what's the standard way to get a single-cast delegate?




use Action (for a delegate method not returning any value) or Func( for one which does). There are generic overloads for 0..8 paramaters in each case. A delegate seems to be an array of Action.


Share this post


Link to post
Share on other sites

use Action (for a delegate method not returning any value) or Func( for one which does). There are generic overloads for 0..8 paramaters in each case. A delegate seems to be an array of Action.


Are there any alternatives that can be used when .NET 2.0 is the target framework? Func is purely .NET 3.5+, and Action is only .NET 2.0 if you only use 1 parameter (0,2+ are all .NET 3.5+).

I might be able to get by with Action (single parameter and no return type), but it won't be pretty... :(

Share this post


Link to post
Share on other sites
Why not just use a delegate and just tell people not to multi-subscribe? If you need a return value, store it in the EventArgs (examine how the CancelEventArgs pattern works).

The better option would be to upgrade to C# 3.0+ and .Net 3.5+; the new features make functional programming much easier.

Share this post


Link to post
Share on other sites

Why not just use a delegate and just tell people not to multi-subscribe?


Are you being sincere? :blink:


If you need a return value, store it in the EventArgs (examine how the CancelEventArgs pattern works).


Yah, that's what I had in mind; the KeyPressEventArts from Windows.Forms uses a 'Handled' property that has identical functionality to the 'bool' that would have normally been my return value.

Share this post


Link to post
Share on other sites

use Action (for a delegate method not returning any value) or Func( for one which does). There are generic overloads for 0..8 paramaters in each case. A delegate seems to be an array of Action.


This does not prevent multi-assignment. They're still delegates and as such are multicast.


The only way you're going to be able to provide a single-cast delegate is by wrapping it in a class which does assignment to the delegate and re-exposes some calling mechanism. That's going to be awkward to write and more awkward to use.

Why exactly do you need to prevent mutlicasting? A user can simply do:


del = delegate(){ a(); b(); };


instead of


del += a;
del += b;

Share this post


Link to post
Share on other sites

The only way you're going to be able to provide a single-cast delegate is by wrapping it in a class which does assignment to the delegate and re-exposes some calling mechanism. That's going to be awkward to write and more awkward to use.


Agreed; if I can't do this cleanly with a delegate, I wonder if I could solve this with an interface. :mellow:

For instance, instead of a delegate based design:
[source lang=csharp]
SwimmingPool swimpool = new SwimmingPool();
swimpool.Overflow = new OverflowDelegate(PoolOverflowed);
swimpool.Overflow += PoolOverflowed; /* attempting to prevent this
(user may be tempted to write this in later files, without realizing they don't have to!) */
[/source]

To replace the delegate with just an interface that would get called:
[source lang=csharp]
SwimmingPool swimpool = new SwimmingPool();
swimpool.IOverflow= this; /* no temptation to "+=" later, though in my
situation this should never get changed after it has been set -- and yet it still can be! */
[/source]

Hmmm, maybe if I made it readonly; SwimmingPool(IOverflow overflow)...
[source lang=csharp]
SwimmingPool swimpool = new SwimmingPool(this);
// swimpool.IOverflow = this; // <-- would not compile =D
[/source]

Alright, I think I've got a work-around. :D

Share this post


Link to post
Share on other sites
I would create a wrapper class around the delegate.


public class SingleDelegate
{
public delegate void MyDelegate();
private MyDelegate invocation;
public MyDelegate Invocation
{
get
{
return invocation;
}
set
{
if (invocation == null)
{
invocation = value;
}
else
{
// Re-assign, leave aside or something else.
}
}
}
}





SingleDelegate m = new SingleDelegate() { Invocation = MyFunc };
m.Invocation();

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!