C#类型参数不能从Select中的使用推断出来,并有多个返回 [英] C# type arguments cannot be inferred from usage in Select with multiple returns

查看:144
本文介绍了C#类型参数不能从Select中的使用推断出来,并有多个返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不认为我所做的任何事情都太深奥了,但是我对此没有其他疑问.

I don't think I'm doing anything too esoteric, but I don't see any other questions about this.

以下代码(我已将其简化为要点)在C#4中产生了编译器错误.但是,显而易见的是类型参数是-最大的公分母(类A")也是如此.在方法"Frob"的返回类型中显式定义.编译器是否应该在lambda表达式中列出所有返回类型的列表,创建一个祖先树以查找其共同祖先,然后将其与包含方法的预期返回类型进行调和?

The following code (I've reduced it to the essentials) generates a compiler error in C# 4. However, it should be obvious what the type argument is - there's a greatest common denominator ("class A") that is also explicitly defined in the return type of the method "Frob". Shouldn't the compiler make a list of all the return types in the lambda expression, create an ancestry tree to find their common ancestors, and then reconcile that with the expected return type of the containing method?

无法从用法中推断出方法'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable,System.Func)'的类型参数.尝试显式指定类型参数.

The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Sample
{
    public abstract class A
    {
        private A(int index) { /* ... */ }

        public sealed class A1 : A
        {
            public A1(string text, int index)
                : base(index)
            { /* ... */ }
        }

        public sealed class A2 : A
        {
            public A2(int index)
                : base(index)
            { /* ... */ }
        }

        private static Regex _regex = new Regex(@"(to be)|(not to be)");
        public static IEnumerable<A> Frob(string frobbable)
        {
            return _regex.Matches(frobbable)
                .Cast<Match>()
                .Select((match, i) =>
                {
                    if (match.Groups[1].Success)
                    {
                        return new A1(match.Groups[1].Value, i);
                    }
                    else
                    {
                        return new A2(i);
                    }
                });
        }
    }
}

推荐答案

这是C#4规范的7.5.2.12节:

It's section 7.5.2.12 of the C# 4 spec:

在类型推断和重载解析期间使用匿名函数F的推断返回类型.只能为已知所有参数类型的匿名函数确定推断的返回类型,这是因为它们是通过匿名函数转换提供的显式给定的,或者是在对封闭的泛型方法调用进行类型推断时推断出来的.推断的返回类型确定如下:

The inferred return type of an anonymous function F is used during type inference and overload resolution. The inferred return type can only be determined for an anonymous function where all parameter types are known, either because they are explicitly given, provided through an anonymous function conversion or inferred during type inference on an enclosing generic method invocation. The inferred return type is determined as follows:

  • 如果F的主体是一个表达式,则F的推断返回类型就是该表达式的类型.
  • 如果F的主体是一个块,并且该块的return语句中的表达式集具有最佳通用类型T(第7.5.2.14节),则推断出的F的返回类型为T.
  • 否则,无法为E推断返回类型.

第7.5.2.14节是:

Section 7.5.2.14 is this:

在某些情况下,需要为一组表达式推断一个公共类型.特别是,以这种方式可以找到隐式类型数组的元素类型和带有块主体的匿名函数的返回类型.

In some cases, a common type needs to be inferred for a set of expressions. In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.

直观地,给定一组表达式E1…Em,该推论应该等效于调用方法

Intuitively, given a set of expressions E1…Em this inference should be equivalent to calling a method

Tr M<X>(X x1 … X xm)

以Ei作为参数.

更精确地说,推断是从一个未固定的类型变量X开始的.然后从每个Ei到X进行输出类型推断.最后,X是固定的,并且如果成功,结果类型S是得到的最佳通用类型.表达式.如果不存在这样的S,则表达式没有最佳的通用类型.

More precisely, the inference starts out with an unfixed type variable X. Output type inferences are then made from each Ei to X. Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions. If no such S exists, the expressions have no best common type.

所以,假设我们有:

void M<X>(X x1, X x2) {}

A1 a1 = new A1();
A2 a2 = new A2();
M(a1, a2);

...将无法确定X的类型参数,因此返回值推断也以相同的方式失败.

... that would fail to determine a type argument for X, so return value inference fails in the same way.

我怀疑如果将返回值的 都强制转换为A,则它将起作用.

I suspect that if you cast either of your return values to A, it will work.

这篇关于C#类型参数不能从Select中的使用推断出来,并有多个返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆