Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Task doesn't return null

I'm working with the new Task Parallel Library and today went to this case:

This code doesn't compile:

    internal Task<Guid?> SavePages(string[] pages)
    {
        return Task.Run(() =>
        {
            if (pages == null || pages.Length == 0)
                return null;

            ....

Unless I explicitly returns a null nullable Guid:

    internal Task<Guid?> SavePages(string[] pages)
    {
        return Task.Run(() =>
        {
            if (pages == null || pages.Length == 0)
                return (Guid?)null;

            // Check documents path access

Why this behavior, I'm I doing something wrong? I mean, I get the code to work with the second option but don't know If I'm misusing the library, I mean, null is always null, isn't it?

Compile error:

Cannot convert lambda expression to delegate type 'System.Func' because some of the return types in the block are not implicitly convertible to the delegate return type

http://msdn.microsoft.com/en-us/library/dd460717.aspx

like image 437
Erre Efe Avatar asked Feb 20 '23 23:02

Erre Efe


2 Answers

This has to do with the way the compiler determines the type of your lambda. When you return a plain null, the only thing the compiler can imply is that you are returning an object. Hence, your parameterless lambda is compatible with Task<object>. However, the signature of your function says that you are returning Task<Guid?>, so the return type the compiler implied from your code is not compatible. When you cast that null to Guid?, you provide the compiler a the clue it is missing to make the lambda a Task<Guid?>.

like image 91
Sergey Kalinichenko Avatar answered Feb 23 '23 23:02

Sergey Kalinichenko


This is a limitation with type inference in the C# compiler. This issue is not unrelated to the one involving the ternary operator:

int? num = a != null ? a.Value : null;         // Will not compile
int? num = a != null ? a.Value : (int?)null;   // Compiles
int? num = a != null ? (int?)a.Value : null;   // Compiles

Another workaround for your specific situation is to specify the generic type explicitly:

return Task.Run<Guid?>(() =>
{
    if (pages == null || pages.Length == 0)
        return null;
like image 26
Douglas Avatar answered Feb 23 '23 21:02

Douglas