What to use? delegate, event or func <T>?

I want to give objects in the class library the ability to "output" messages without worrying about how they are displayed. The class library can be used in a console application, WindowsForm or a Windows WPF application, or on a web page.

The identifier initially decided that I would use a delegate to handle this. I implemented this using classes, but the compiler did not like the delegate when I tried to put the delegate in the interface from which each of these objects was created.

I found that I can get the delegate out of the interface and then was able to compile, but I'm not sure if this does what I'm trying to do. It also looks like kludge, so I wanted to ask if any of you have different ideas to accomplish this ...

Interface:

namespace Test { using System; using System.Xml.Linq; public interface IAction { DisplayMessageDelegate DisplayMessage(string message); void Execute(); XElement Serialize(XName elementName); } public delegate void DisplayMessageDelegate(string message); } 

From there, I'm not sure how to implement this behavior: (BTW, I know this code will not compile ...)

 public class ActionClass1 : IAction { // Other methods not shown... void Execute() { if (this.DisplayMessage != null) { this.DisplayMessage("Hello"); } } } public class ConsoleClass { ActionClass1 class1 = new ActionClass1(); class1.DisplayMessage = { x => Console.WriteLine(x); }; } public class WinFormClass { ActionClass1 class1 = new ActionClass1(); Class1.DisplayMessage = {x => DisplayTextBox.Text = x; }; } 
+7
source share
6 answers

If you want to connect multiple delegates to answer a single Execute call, I definitely use event . If you want only one action to be connected, use an Action or Func delegate.

For your example, one of the Action delegates should work. In your case, this will be an Action<string> , since your delegate takes a string argument. Action is just a delegate that takes zero or more arguments and returns void. It seems that you are not returning anything, so I suggest Action .

You want to use Func<TResult> if your delegate needs to return something. The difference between Func and Action is that Func delegates have a return type, but Action delegates do not. Any of these delegates have common versions that can accept up to 16 arguments.

If you need more than 16 arguments for the delegate, you can revise the design :)

+11
source

You can do this using Action<string> .

You would not want to use Func<T> , since this defines a delegate that does not accept any arguments but returns a single value of type T. Action<T> , on the other hand, is a delegate that takes a single argument of type T.

I would suggest trying:

 public interface IAction { Action<string> DisplayMessage { get; set; } void Execute(); XElement Serialize(XName elementName); } 

Once you have implemented this interface (fully), you can use it through:

 public class ConsoleClass { public void SomeMethod() { ActionClass1 class1 = new ActionClass1(); class1.DisplayMessage = x => Console.WriteLine(x); } } 

Or:

 public class ConsoleClass { public void SomeMethod() { ActionClass1 class1 = new ActionClass1(); class1.DisplayMessage = this.Print; } private void Print(string message) { Console.WriteLine(message); } } 

You could do the same with events, but I would question it. Your API describes the action that should happen, rather than the event you are responding to - and therefore I would not recommend the event.

+4
source

Incorrect definition of your interface. You will need to specify it like this:

 namespace Test { using System; using System.Xml.Linq; public interface IAction { DisplayMessageDelegate DisplayMessage { get; set; }; void Execute(); XElement Serialize(XName elementName); } public delegate void DisplayMessageDelegate(string message); } 

and then implement the interface.

+1
source

Here

 DisplayMessageDelegate DisplayMessage(string message); 

you describe a method that takes a string and returns DisplayMessageDelegate. Use

  event DisplayMessageDelegate DisplayMessage; 

instead.

+1
source

Personally, I would like you to be better off having an abstract base class that defines an abstract method called DisplayMessage , and then extend that base class by calling it to change the behavior of the way messages are displayed.

0
source

Instead:

 DisplayMessageDelegate DisplayMessage(string message); 

do:

 event Action<string> DisplayMessage; 

Then use DisplayMessage for each item, events are delegates.

0
source

All Articles