I am trying to understand "callback pattern". Every answer says that this is done with delegates (which I know them). But the codes on the answers are something like that:
public delegate void Callback(string result);
public void Test()
{
CallBack callback = CallbackFunction;
DoWork(callback);
}
public void DoWork(CallBack callback)
{
callback("Hello world");
}
public void CallbackFunction(string result)
{
Console.WriteLine(result);
}
I really don't understand, why we need delegate for this? We can do this in this way too?
public void Test()
{
DoWork();
}
public void DoWork()
{
CallbackFunction("Hello world");
}
public void CallbackFunction(string result)
{
Console.WriteLine(result);
}
Besides that, for example in Java, a callback means a real "return" to the main program's "particular function" after an event. But when we use delegates, isn't this just calling another method?
How can we make a callback that finally calls an OnFail() method on fail, and OnSuccess() method on success. I am really confused. Can somebody help me to understand this?
A delegate safely encapsulates a method, a kind of a template to a function in its signature. Sometimes it is easy to think it is a pointer to a function.
In your sample, the CallbackFunction can be setted to Callback because both in its definition takes just a string argument.
You could use Action and Func instead of delegate. The difference between them is that an Action does not return something and Func does. For sample:
public void Test(Action success, Action<Exception> error)
{
try
{
// perform some task
success();
}
catch (Exception ex)
{
error(ex);
}
}
And use it:
Test(() => { Console.WriteLine("Success"); },
(ex) => { Console.WriteLine($"Error: {ex.Message}"); });
the generic option of an Action is the type of the arguments you can pas to this method. On the sample, Exception is a argument which is passed to error Action. The same is valid for a Func<> but the last type of a Func is the result type.
Why do we need delegates?
Because in many programs, you need the ability to abstract the concept of a method. One reason is events, another is a set of methods like this:
public void DoWork(Action completeCallback)
{
... //Do Stuff
completeCallback();
}
public void FirstMainMethod()
{
DoWork(() => Console.WriteLine("First callback");
}
public void SecondMainMethod()
{
DoWork(() => Console.WriteLine("Second callback");
}
In other words, different parts of my code need to have a different method run on completion, so I pass it in (I can't use a direct call). The delegate abstraction allows this. Also note that the idea of a "completion" callback in .NET is pretty silly, you almost never need it. You will use delegates for this general idea all the time though.
How can we make a callback that finally calls an OnFail() method on fail, and OnSuccess() method on success?
You can do this pretty easily. You can even make a somewhat generic one (not sure if you would ever want to mind you, but the following code works):
public void SuccessFailHelper(Func<bool> work, Action success, Action failure)
{
if (work())
success();
else
failure();
}
Related
I would like to create a pattern like the following:
namespace SharedUtilities
{
public partial class PartialClass
{
public void DoSomethingInteresting()
{
DoSomethingPlatformSpecific();
}
partial void DoSomethingPlatformSpecific();
}
}
But I would like to add a callback argument so that I can pass in a different callback depending on the platform. Can anyone point me in the right direction here? I have been reading up on Action, EventHandler<>, and delegate, but I'm not sure which one to use in this scenario. Any advice would be appreciated.
There are a lot of ways to do that and handle this kind of scenario, the simplest one would be like this -
namespace SharedUtilities
{
public partial class PartialClass
{
public void DoSomethingInteresting(Action<Type1, Type2> action)
{
//code logic
action(p1, p2);
}
}
}
Then use it like this -
With lambda
(new SharedUtilities.PartialClass()).DoSomethingInteresting((param1, param2)=>
{
//codes
});
Without Lambda
public void DoSomethingInterestingSpecific(Type1 param1, Type2 param2)
{
//code logic
}
(new SharedUtilities.PartialClass()).DoSomethingInteresting(DoSomethingInterestingSpecific);
That is one way of doing this, there are other ways too, like abstract factory pattern, event delegate callback, etc.
Func<...> has a return value, Action<...> does not. Callbacks should usually be Action<...>
If you want to structure the code such that classes other than the one calling the function can be notified when it's complete, define an event.
I'm trying to implement fire and forget functionality, using the Task Parallel Library. With an inline call to Task.Factory.StartNew, everything works as expected. However, I want to move the Task.Factory.StartNew call into a separate class so that I can add logging, error handling, etc, and potentially upgrade the code in the future as better threading classes, etc are added to the .NET Framework, without duplicating code.
Below is a unit test that I would expect to pass, but that does not. I would appreciate help trying to figure out how to make this work.
[TestFixture]
public class ThreadingServiceFixture
{
public static bool methodFired = false;
[Test]
public void CanFireAndForgetWithThreadingService()
{
try
{
var service = new ThreadingService();
service.FireAndForget(() => methodFired = true);
var endTime = DateTime.Now.AddSeconds(1);
while(DateTime.Now < endTime)
{
//wait
}
Assert.IsTrue(methodFired == true);
}
finally
{
methodFired = false;
}
}
}
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action);
}
}
You're not executing the action, you're just returning it.
Try:
return Task.Factory.StartNew(() => action());
If is "fire and forget" you don't need to return the Task from the FireAndForget method, because the caller could get that Task and cancel it (strictly speaking the caller would "remember" of the call).
If you want to invoke this method from many services that do not inherit from a common ThreadingService you can implement an extension method via an interface.
public interface IFireAndForget
{
// no member needed.
}
public static class FireAndForgetExtensions
{
public static void FireAndForget(this IFireAndForget obj, Action action)
{
// pass the action, not a new lambda
Task.Factory.StartNew(action);
}
}
// using
public class ThreadingService : IFireAndForget
{
}
Also note the in your method you have to pass the action to the StartNew method insted of pass a lambda that return the action parameter.
You did not invoke the action in the ThreadingService
The code should read something like
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action.Invoke());
}
}
Additional note: testing state with a public field is evil. Think about repeatability, maintenance, running tests in different order. You should move bool methodFired inside the test. I would also assume there is a better technique to test this (but I am not sure which one).
Testing threaded code is hard.
Basing your tests on timing is a bad idea, they may become non-deterministic and you might observe erratic behavior on you build server. Imagine a tests that sometime passes and sometimes doesn't!
Your code has a bug, since you are not actually invoking the action.
But consider this variation:
[Test]
[TimeOut(5000)]
public void CanFireAndForgetWithThreadingService()
{
var service = new ThreadingService();
ManualResetEvent mre = new ManualRestEvent(bool); // I never remember what is the default...
service.FireAndForget(() => mre.Set() /*will release the test asynchroneously*/);
mre.WaitOne(); // blocks, will timeout if FireAndForget does not fire the action.
}
Yes, we are still using timing. But the test the timeout will happen only if the code breaks!
In all other scenarios, the test is absolutely predictable and takes a very short amount of time to execute, no waiting and praying for timing issues not to happen ;-)
I've got this code (well, something similar).
private delegate void GenericCallback<T>(T Info);
private void DoWork()
{
System.Threading.Thread Worker = new System.Threading.Thread(
delegate()
{
TestMethod(TestMethodCallback<string>);
}
);
Worker.Start();
}
private void TestMethod(GenericCallback<string> Callback)
{
System.Threading.Thread.Sleep(1000);
if(Callback != null)
{
Callback("Complete");
}
}
private void TestMethod(GenericCallback<int> Callback)
{
System.Threading.Thread.Sleep(1000);
if(Callback != null)
{
Callback(25);
}
}
private void TestMethodCallback<T>(T Info)
{
MessageBox.Show(Info.ToString());
}
Which allows me to call different versions of TestMethod based on the type of a parameter, while also allowing me to have a single callback method.
Is this bad form, or an accepted practice?
It looks like you might be looking for the Action delegate type. It's basically what you have here: a generic void-returning delegate type.
Such an established practice, that some of the work has been done for you. Action in this case, and Func should you return a value, are generic delegates, precisely like this. An advantage is, if I saw your signature:
private void TestMethod(GenericCallback<string> Callback)
I have to look up what GenericCallback<string> is. If I saw:
private void TestMethod(Action<string> callback)
I already know.
Totally fine. In this very simple case it might be preferable to specify a string (since your generic type, with no constraints, can only be dealt with as an Object and so ToString() is one of the very few useful things you can call no matter what you pass), but obviously this is example code so there are very many accepted ways to do this. Action<> and Func<> are indeed good built-ins to know about, but they have some drawbacks, such as reduced self-documentation (it can be difficult to tell what a Func is expected to do, other than the obvious "take an integer and return an integer".
Assuming that this would be used for returning data asynchronously (otherwise, why not wait for the return value?), it sounds like you haven't discovered Task Parallel Library. In particular, Task<T> is a more generalized way of acheiving callback-like behaviour.
For instance:
private Task<int> TestMethod()
{
TaskCompletionSource<int> tcs=new TaskCompletionSource<int>();
//do something asynchronous
//when asynchronous job is complete
//tcs.SetResult(25);
return tcs.Task;
}
I have a C# class that has some functionality that I'd like to allow a client of the class to override. Specifically I'd like the following:
If the client does nothing, they get our default behavior
The client can override the behavior and cause our default behavior to not be called.
The client can override the behavior and cause our default behavior to be called as a pre/post/middle operation.
My current thinking is to:
Expose an event that the client would subscribe to if they wanted to override the behavior.
Expose a method with the default behavior (that matches the signature of the event):
void DefaultBehavior()
Whenever we attempt to fire the event, if the delegate is null, we call our default behavior method, otherwise, we call the delegate of the event:
if (eventDelegate == null)
DefaultBehavior();
else
eventDelegate();
When the client overrides the behavior they can optionally call our DefaultBehavior method to get the desired behavior.
Do you think this approach will be intuitive enough from the client's perspective? Or can you suggest any alternatives that might be better?
Well, if you want your client to override some behavior, why not create a virtual function, an let the client actually override it?
It's the straightforward way of accomplishing this. No need to reinvent the wheel.
If I understand your question, by client you mean some code calling your class, and not overriding your class, assuming you need to do it this way (I agree with #zmbq answer if you can do it that way):
You can make your method have 2 overloads, one with no parameters and another receiving a Action object
public void methodName()
public void methodName(Action delegate)
then in the body of methodName() you will call the other method with defaultAction
public void methodName()
{
methodName(DefaultBehavior);
}
finally in the second method you just call the delegate passed as parameter, without caring if it's the default or not
public void methodName(Action delegate)
{
delegate();
}
the client of your class will see this two overloads and decide wether to use the default or give a custom behavior
EDIT:
Ok, last try :), according to your last comment would it work for you to have an instance field
private Action behaviorDelegate = DefaultBehavior;
Anywhere in your class you can assign to behaviorDelegate a different behavior, and then you don't need an if statement since the behavior will always be in delegate variable whether it is the default or not. It is not a big change but it seems cleaner to me.
You could (perhaps?) also do it without events:
Declaration:
public class DemoClass
{
public delegate string MyDelegate(string testValue);
public static MyDelegate DefaultBehavior
{
get
{
return testValue =>
{
return String.Concat(testValue,
", now with 99% more exclamation points!!!!!!!!");
};
}
}
public MyDelegate ModifyString = testValue =>
{
return DemoClass.DefaultBehavior(testValue);
};
}
Use:
// first, default:
DemoClass demoObject = new DemoClass();
Console.WriteLine(demoObject.ModifyString("My test string"));
// now, pure "override":
demoObject.ModifyString = testVal =>
{ return String.Concat(testVal, ", this time with question marks????");
};
Console.WriteLine(demoObject.ModifyString("Second test string"));
// finally, define a delegate that overrides and calls default:
DemoClass.MyDelegate combined = testVal =>
{ return String.Concat(DemoClass.DefaultBehavior(testVal),
", now we're really tricky");
};
demoObject.ModifyString = combined;
Console.WriteLine(demoObject.ModifyString("Third test string"));
Output:
My test string, now with 99% more exclamation points!!!!!!!!
Second test string, this time with question marks????
Third test string, now with 99% more exclamation points!!!!!!!!, now we're really tricky
Just use a virtual method:
public class BaseClass {
public virtual void Something() {
Console.WriteLine("base functionality");
}
}
public class Sub1 : BaseClass {
public override void Something() {
// do whatever you want here
base.Something(); // don't call it at all if you like
// do whatever you want here
}
}
Here is my scenario.
I have class with 10 methods, those methods are atomic, and are only 10 lines of code max.
So I was thinking, instead of handling the exceptions in each function, would it be possible, to create a delegate (? not sure its the right word here)
That so called wrapped function would execute those atomic functions and handle their exceptions, thus allowing me to centralize exception handling.
Is this possible in C# using delegate or Func, or maybe there is another way to centralize error handling that I might have missed?
Thanks in advance
Yes it is possible here is a code example
using System;
namespace ConsoleApp
{
class Example {
public void Run() {
catchy(crashA); // Calling defined functions
catchy(crashB);
catchy(()=> {
throw new ArgumentException("Anonymous function...");
});
}
void crashA() {
//...
throw new ArgumentException("another error");
}
void crashB() {
//...
throw new ArgumentException("another error");
}
void catchy(Action action) {
try {
action();
} catch (Exception ex) {
Console.WriteLine(ex);
// do something
}
}
}
class MainClass
{
public static void Main (string[] args)
{
new Example().Run();
Console.ReadLine();
Console.WriteLine ("Hello World!");
}
}
}
yes, with a delegate like this
private delegate MyReturnType MyDelegate(params Object[] a);
but it won't be type safe.
I am not sure if this would work for you, but you could possibly use the "Hole In The Middle" pattern or build an abstract class.
I was trying to do something similar where I wanted certain Pre and Post conditions to occur each time a given method was called. In the same manner you could possibly put your Exception logic there instead of the Pre and Post conditons. Look at this post.
Hope it helps.