# [.net] Single-cast delegate?

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

## 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...

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 on other sites

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...

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 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 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 on other sites

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

Are you being sincere?

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 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(); }; 

 del += a; del += b; 

##### 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.

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]

[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.

##### Share on other sites
Why do you want this, sounds weird.

##### 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(); 

1. 1
Rutin
49
2. 2
3. 3
4. 4
5. 5
JoeJ
19

• 11
• 16
• 9
• 10
• 13
• ### Forum Statistics

• Total Topics
633003
• Total Posts
3009846
• ### Who's Online (See full list)

There are no registered users currently online

×