无法从具有多个返回的 Select 中的用法推断出 C# 类型参数

标签 c# linq generics inheritance

我不认为我在做任何太深奥的事情,但我没有看到任何其他关于此的问题。

以下代码(我已将其简化为基本要素)在 C# 4 中生成编译器错误。但是,类型参数是什么应该是显而易见的 - 最大公分母(“A 类”)也是在方法“Frob”的返回类型中明确定义。编译器不应该列出 lambda 表达式中的所有返回类型,创建一个祖先树来找到它们的共同祖先,然后将其与包含方法的预期返回类型进行协调吗?

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 节:

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:

  • If the body of F is an expression, then the inferred return type of F is the type of that expression.
  • If the body of F is a block and the set of expressions in the block’s return statements has a best common type T (§7.5.2.14), then the inferred return type of F is T.
  • Otherwise, a return type cannot be inferred for E.

第 7.5.2.14 节是这样的:

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.

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

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

with the Ei as arguments.

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 的类型参数,因此返回值推断以同样的方式失败。

我怀疑如果将返回值中的任一个转换为A,它会起作用。

关于无法从具有多个返回的 Select 中的用法推断出 C# 类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11587536/

相关文章:

java - 如何返回列表中的最后一个通用对象? java

java泛型,如何从两个类扩展?

c# - C# 中的 Java 方法 'MessageDigest.getInstance()' 相当于什么?

c# - 删除硬编码值到 app.config 文件

c# - 调用异步方法时对象引用未设置到对象的实例

c# - 如果 DataRowCollection 的基类派生自 IEnumerable<T>,为什么不能在 DataRowCollection 上使用 LINQ

静态成员约束函数的性能

c# - 我如何使用自动映射器和数据库中的 int 将 int 转换为枚举和字符串

c# - LINQ to SQL 为类似的分组依据表达式生成不同的查询

c# - Linq 通过变量访问属性