Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if Object is Task or Task<TResult>

In the sample code (it does not compile because of the invalid if check) below I need to figure out if returnValue is a "Task of TResult" or a Task or another type. If it's Task of TResult I can access and log the Result property,if it's a Task, there is no return value and I log "[Task]", if it's neither of these two then I can directly log the return value or log a ["null"]

public void LogReturnValue(obj returnValue)
{
   var valueToLog = "";
   if(returnValue is Task)
   {
       valueToLog = "[Task]";
   } else if(returnValue is Task<T>)
   {
     valueToLog = returnValue.Result;
   } 
   else 
   {
     valueToLog = returnValue ?? "[null]"
   }
   this.logger.Log(valueToLog);
}

I want to determine if returnValue is a Task or Task of TResult and then take if its the latter, I need to extract the appropriate value from the Result. One idea I have is checking the IsGenericType property, but I am not sure if that will work always.

like image 804
Sushant Avatar asked Oct 17 '17 00:10

Sushant


3 Answers

There may be a cleaner way, but this works and you can build on it. "as" will check the type or base type is a task, then you can inspect the type to see if it has generic type arguments or not. Because it's dynamic, the check for Result being a property is done at runtime instead of compile time.

static void outType(object returnValue)
{
    dynamic task = returnValue as Task;
    if ( task != null )
    {
        var gargs = returnValue.GetType().GenericTypeArguments;

        if (gargs.Count() == 0)
        {
            Console.WriteLine("Task");
        }
        else
        {
            var result = task.IsCompleted ? task.Result : "[Not Complete]";
            Console.WriteLine("Task<{0}> : {1}", gargs[0].Name, result);
        }
    }
}
like image 24
Tony Lee Avatar answered Oct 18 '22 20:10

Tony Lee


Despite Eric Lippert mentioned that you should not fetch Task.Result, there are a few questions to answer:

  1. How to check if an object is a generic type

    obj.GetType().IsGenericType
    
  2. Whether it's Task<TResult>

    obj.GetType().GetGenericTypeDefinition() == typeof(Task<>)
    
  3. How to access a generic property value

    obj.GetType().GetProperty("Result").GetValue(obj) // This value could be null
    
like image 166
qxg Avatar answered Oct 18 '22 20:10

qxg


I feel like either none of the preceding answers clearly answered the question being asked, or I rather missed the mark on the intent of the question.

What I interpreted from the question was:

"How do I tell if 'returnValue' is of Type 'Task', 'Task<>', or something else?

This test code may be used to determine this:

    Task voidTask = new Task(() => { return; });
    Task<object> valTask = new Task<object>(() => { return null; });

    Type voidTaskType = voidTask.GetType();
    Type valTaskType = valTask.GetType();

    Console.WriteLine($"voidTaskType is Task : {voidTask is Task}");
    Console.WriteLine($"valTaskType is Task : {valTask is Task}");
    Console.WriteLine($"voidTaskType.IsGenericType : {voidTaskType.IsGenericType}");
    Console.WriteLine($"valTaskType.IsGenericType : {valTaskType.IsGenericType}");

The results are as follows:

voidTaskType is Task : True
valTaskType is Task : True
voidTaskType.IsGenericType : False
valTaskType.IsGenericType : True
like image 1
Mitselplik Avatar answered Oct 18 '22 19:10

Mitselplik