C# 为什么任务没有';t返回空值

C# 为什么任务没有';t返回空值,c#,task-parallel-library,C#,Task Parallel Library,我正在与新员工合作,今天我们讨论了这个案例: 此代码不编译: internal Task<Guid?> SavePages(string[] pages) { return Task.Run(() => { if (pages == null || pages.Length == 0) return null; .... 内部任务保存页(字符串[]

我正在与新员工合作,今天我们讨论了这个案例:

此代码不编译:

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

            ....
内部任务保存页(字符串[]页)
{
返回任务。运行(()=>
{
if(pages==null | | pages.Length==0)
返回null;
....
除非我显式返回空的可空Guid:

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

            // Check documents path access
内部任务保存页(字符串[]页)
{
返回任务。运行(()=>
{
if(pages==null | | pages.Length==0)
返回(Guid?)null;
//检查文档路径访问
为什么会有这种行为,我做错了什么?我的意思是,我让代码使用第二个选项,但不知道我是否滥用了库,我的意思是,null总是null,不是吗

编译错误:

无法将lambda表达式转换为委托类型 “System.Func”因为返回 块中的类型不能隐式转换为委托 返回类型


这与编译器确定lambda类型的方式有关。当您返回纯
null
时,编译器只能暗示您正在返回一个对象。因此,无参数lambda与
任务
兼容。但是,函数的签名表示您正在返回
>任务
,因此编译器从代码中暗示的返回类型不兼容。当您将
null
强制转换为
Guid?
时,您向编译器提供了使lambda成为
任务

的线索。这是C编译器中类型推断的限制。此问题与invol无关对三元运算符进行排序:

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;
返回任务。运行(()=>
{
if(pages==null | | pages.Length==0)
返回null;

FFR,包括确切的编译器错误将非常有用,因为在这种情况下,它可能会提到无法推断类型。问题是null始终为null,因此编译器无法知道您使用null表达式表示的是哪种类型侧注:与
(Guid?.null
新的Guid?()
默认值(Guid?
)。编译器应该自己推断出这一点(尽管原因很清楚)@zmbq如何确定
null
的类型?它是所有引用类型的有效值,因此编译器无法确定该表达式的类型(对象除外)@RuneFS假定它是一个可为空的类型,那么assign必须起作用,不是吗?可以从保存页的类型推断出该类型。@zmbq在C#中,类型推断不是这样工作的。通常,每个表达式的类型都是独立推断的(但lambda是一个例外).1道格拉斯的解释。一个问题:是否使用非通用版本的Task.Run(如您所建议的那样)以任何可能的方式降低性能?除非我遗漏了什么,否则他只是在说不要让编译器推断类型-无论哪种方式,都会得到相同的生成ILAFAICT@RandolfRincón-Fadul:我的代码仍然使用的是的泛型版本;事实上,它是显式使用的,而不是推断类型(就像您的代码那样)就像James Manning所说的,我不相信生成的IL会有什么不同,因为在编译时执行类型推断。显式指定泛型类型可能会使编译(不是运行时)稍微快一点,但这几乎是绝对不需要考虑的。