1

So basically T has a return type, I want to get back the generic return type. Example:

private TResult EndInvoke<T, TResult>(Func<T, TResult> asyncCaller, IAsyncResult asyncResult)
{
    TResult result = default(TResult);

    try
    {
        result = asyncCaller.EndInvoke(asyncResult);
    }
    catch (Exception exception)
    {
       // get exception details.
    }

    return result;
}

How do I pass just the T calling the method and get the TResult? Mind you, I only have the T.

EDIT: I meant how do I call this method?

EDIT: I want a generic EndInvoke, because I am a huge try catch on different EndInvokes, then I want the result from the EndInvoke.

MilkTea027
  • 301
  • 1
  • 5
  • 24
  • 1
    I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Feb 17 '14 at 07:26
  • `So basically T has a return type` Actually, you have return type `TResult`. The question is unclear. – Hamlet Hakobyan Feb 17 '14 at 07:29
  • This function looks like its whole point (in combination with another function, probably named `BeginInvoke`) is to enable asynchronous calls. If you only have the `T`, want to call `asyncCaller`, and want to handle the result in that very same function, you can only use a synchronous call. Can you clarify what it is you're trying to do? –  Feb 17 '14 at 07:44
  • I don't think that is possible. For a generic type, you need to either mention the type in the definition as the type parameter T or TResult. If you just want to mention T and not TResult in method definition, how does it know what TResult can be? You can either use dynamic or object result type for that purpose. – Shakti Prakash Singh Feb 17 '14 at 07:45
  • You say you want a generic EndInvoke. You've got a generic EndInvoke. What is the problem you're having? After your next edit, please re-read your question, and see if you would understand what is being asked if someone else asked the question. –  Feb 17 '14 at 07:58
  • I suppose you could turn this into an extension method. Is that an acceptable solution? – Steven Liekens Feb 17 '14 at 08:03
  • @hvd: Please read the part: I meant how do I call this method? – MilkTea027 Feb 17 '14 at 08:04
  • @MilkTea027 Please read my earlier question. Calling this method makes no sense if you only have the `T`. –  Feb 17 '14 at 08:16
  • @hvd Then the method is wrongly implemented for the generic EndInvoke because I want a try catch around the generic EndInvoke then return the TResult.. To clarify.. What is the correct implementation then? – MilkTea027 Feb 17 '14 at 08:22
  • @MilkTea027 Oh wait... So you don't have a *value* of type `T`, you have the *type* `T`. A simple approach, if your goal is to make it work without having to know `TResult`, would be to simply use `Func`. For functions that return a reference type, that means the functions themselves don't even need to change. –  Feb 17 '14 at 08:31
  • This question is melting my brain. Is the problem that you have a value of type `T` but can't determine the type of `TResult`? – Steven Liekens Feb 17 '14 at 08:36
  • Sorry for the confusion, here's the original question: http://stackoverflow.com/questions/21822569/how-to-make-a-generic-delegate-endinvoke – MilkTea027 Feb 17 '14 at 08:44
  • In that question `T` is equal to `TResult`. Is that a coincidence? – Steven Liekens Feb 17 '14 at 08:49
  • No they are not equal. – MilkTea027 Feb 17 '14 at 08:50
  • What do you mean? The first delegate `GetFooAsync1` takes a parameter of type `Foo1` and returns a value of type `Foo1`. In other words: `T == TResult`. – Steven Liekens Feb 17 '14 at 08:54
  • The T I was trying to pass was GetFooAsync1, then I want it to return a Foo1 – MilkTea027 Feb 17 '14 at 08:57
  • @MilkTea027 Then just call `EndInvoke(GetFooAsync1, asyncResult)`? The compiler should be able to figure out the correct `T` and `TResult` from that. –  Feb 17 '14 at 09:01
  • It doesn't work :( I need it to be generic, if it is possible? – MilkTea027 Feb 17 '14 at 09:02
  • @MilkTea027 Oh wait, sorry, yeah, that won't work, because you've got custom delegate types. You don't need custom delegate types, and if you remove them (instead using `Func` everywhere), it would work. –  Feb 17 '14 at 09:05
  • @MilkTea027 Can you comment on my answer explaining why that's not what you need? – Steven Liekens Feb 17 '14 at 09:25

2 Answers2

1

I suggest converting your generic EndInvoke<,> method to an extension method first.

public static class FuncExtensions
{
    public static TResult EndInvoke<T, TResult>(this Func<T, TResult> asyncCaller, IAsyncResult asyncResult)
    {
        // ...
    }
}

This will simplify the method call. As an example, I'll call a method that calculates the square of an integer.

private int Square(int x)
{
    return x * x;
}

In your client code, you'd call it like this:

Func<int, int> caller = new Func<int, int>(Square);

int x = 5;

int y = default(int);

caller.BeginInvoke(x,
    asyncResult =>
    {
        y = caller.EndInvoke(asyncResult);
    },
    null);

Console.WriteLine("The square of {0} is {1}", x, y);

EDIT

This example has not been tested in any way, and contains an obvious race condition.

Steven Liekens
  • 13,266
  • 8
  • 59
  • 85
0

Not sure that I understand correctly, but I think that if you want the Func return value, you should drop the IAsyncResult.

Example:

private TResult GetResult<T, TResult>(Func<T, TResult> asyncCaller, IAsyncResult asyncResult)
    {
        TResult result = default(TResult);
        result = asyncCaller(argument...);

        return result;
    }
Eliran Pe'er
  • 2,569
  • 3
  • 22
  • 33
  • The name of the function in the question, `EndInvoke`, and the `IAsyncResult`, suggest an asynchronous call has already been made, though. –  Feb 17 '14 at 07:42