Tester101
Tester101

Reputation: 8172

Is it bad form to use a generic callback?

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?

Upvotes: 5

Views: 3252

Answers (4)

KeithS
KeithS

Reputation: 71573

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

Upvotes: 1

spender
spender

Reputation: 120488

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;

}

Upvotes: 0

Jon Hanna
Jon Hanna

Reputation: 113322

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.

Upvotes: 5

Thom Smith
Thom Smith

Reputation: 14086

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.

Upvotes: 8

Related Questions