2012-07-01 141 views
4

我与新Task Parallel Library,今天的工作去了这种情况:为什么任务没有返回null

此代码不能编译:

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

      .... 

除非我明确地返回一个空可空Guid:

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

      // Check documents path access 

为什么这种行为,我是我做错了什么?我的意思是,我得到的代码与第二个选项一起工作,但不知道如果我滥用该库,我的意思是,null始终为空,不是吗?

编译错误:

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

+0

FFR,包括确切的编译器错误将是有益的,因为在这种情况下,它可能会提到一些关于不能推断类型的内容。 –

+0

问题在于null始终为空,因此编译器无法知道您使用空表达式表示哪种类型 –

+0

注意:表示“(Guid?)null”的其他两种方法是“new Guid?()'和'default(Guid?)'。 – svick

回答

5

这与编译器确定您的拉姆达类型的方式做。当你返回一个简单的null时,编译器可以暗示的唯一事情就是你要返回一个对象。因此,您的无参数lambda与Task<object>兼容。但是,函数的签名表示您正在返回Task<Guid?>,因此编译器在代码中隐含的返回类型不兼容。当您将该null转换为Guid?时,您向编译器提供了缺少该线索以使lambda a Task<Guid?>

+1

编译器应该自己推断这一点(尽管它很清楚为什么它不) – zmbq

+1

@zmbq你将如何确定'null'类型是什么?它是所有引用类型的有效值,因此编译器无法确定该表达式的类型(除了object以外的任何其他类型) –

+0

@RuneFS鉴于它是可以为空的类型,那么assign必须工作,难道你不是? –

3

这是C#编译器中的类型推断的限制。这个问题不无关系一个涉及三元运算符:

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 

您的具体情况的另一个解决方法是指定的泛型类型明确:

return Task.Run<Guid?>(() => 
{ 
    if (pages == null || pages.Length == 0) 
     return null; 
+0

+1道格拉斯的解释。一个问题:使用非通用版本的Task.Run(如您所建议的)以任何可能的方式降低性能? –

+1

除非我错过了一些东西,他只是在谈论不让编译器推断出这种类型 - 无论哪种方式你都会得到相同的IL AFAICT –

+0

@RandolfRincón-Fadul:我的代码仍然使用['Task.Run']的通用版本] (http://msdn.microsoft.com/en-us/library/hh194921%28v=vs.110%29.aspx);事实上,它明确地*这样做,而不是推断类型(就像你的代码那样)。就像James Manning所说的那样,我不相信生成的IL会有任何不同,因为类型推断是在编译时执行的。显式指定通用类型可能会使编译(* not * runtime)稍微快一些,但这几乎可以肯定永远不需要考虑。 – Douglas