为什么不能C#从这个看似简单的,明显的案例推断类型 [英] Why can't C# infer type from this seemingly simple, obvious case

查看:148
本文介绍了为什么不能C#从这个看似简单的,明显的案例推断类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有鉴于此code:

  C类
{
    C()
    {
        测试<串GT;(A); //罚款
        试验((字符串)= GT; {}); //罚款
        测试((动作<串GT;)A); //罚款        测试(A); //类型参数不能从使用推断!
    }    静态无效测试< T>(动作< T>一种){}    无效A(字符串_){}
}

编译器抱怨测试(A)想不通 T 字符串

这似乎是一个pretty容易的情况下给我,我发誓我在我写的其他通用工具和扩展函数依赖更为复杂的推理。缺少什么我在这里?

更新1:这是在C#4.0编译器。我在VS2010发现的问题,上面的示例是从简单的情况下摄制我LINQPad 4发。

更新2:增加了一些更多的例子来的什么作品名单


解决方案

 测试(A);

这将会失败,因为只适用法(测试< T>(动作< T>))需要类型推断,类型推断算法要求每个每个参数是某种类型的或是匿名函数。 (这实际上是从类型推断算法的规范(第7.5.2节)推断)的方法组 A 是任何类型的(即使它是可转换到一个不适当的委托类型),它是不是一个匿名函数。

 测试<串GT;(A);

这成功,不同的是类型推断是没有必要绑定测试和方法组是可转换为所需的委托参数类型无效动作<串>(串)

 测试((字符串)=> {});

这成功,不同的是类型推理算法的规定了在第一阶段(§7.5.2.1)匿名函数。参数和返回值类型的匿名函数是已知的,所以明显的参数类型推断可以订做,并且correspondense在匿名函数的类型之间,从而制成(无效?(串))和委托类型的测试方法的参数的类型参数(无效动作< T>(T))。没有算法是用于将对应于该算法的匿名函数方法组指定。

 测试((动作<串GT;)A);

这成功,区别在于无类型方法组参数 A 被转换为一个类型,从而使测试的类型推断来与特定类型作为唯一的参数传递给方法的前pression正常进行。

我能想到的在理论上没有理由重载不能尝试的方法组 A 。然后,如果一个最佳的结合中找到,方法组可以给予相同的待遇作为一个匿名函数。这是在这样的地方的方法组包含一个候选人的情况下尤其如此,它有没有类型参数。但是原因,它不工作,C#4似乎是事实,这个功能并没有设计和实施。鉴于此功能的复杂性,它的应用narowness,以及三个简单的变通是否存在等,我不打算拿着我的呼吸吧!

Given this code:

class C
{
    C()
    {
        Test<string>(A); // fine
        Test((string a) => {}); // fine
        Test((Action<string>)A); // fine

        Test(A); // type arguments cannot be inferred from usage!
    }

    static void Test<T>(Action<T> a) { }

    void A(string _) { }
}

The compiler complains that Test(A) can't figure out T to be string.

This seems like a pretty easy case to me, and I swear I've relied far more complicated inference in other generic utility and extension functions I've written. What am I missing here?

Update 1: This is in the C# 4.0 compiler. I discovered the issue in VS2010 and the above sample is from a simplest-case repro I made in LINQPad 4.

Update 2: Added some more examples to the list of what works.

解决方案

Test(A);

This fails because the only applicable method (Test<T>(Action<T>)) requires type inference, and the type inference algorithm requires that each each argument be of some type or be an anonymous function. (This fact is inferred from the specification of the type inference algorithm (§7.5.2)) The method group A is not of any type (even though it is convertable to an appropriate delegate type), and it is not an anonymous function.

Test<string>(A);

This succeeds, the difference being that type inference is not necessary to bind Test, and method group A is convertable to the required delegate parameter type void Action<string>(string).

Test((string a) => {});

This succeeds, the difference being that the type inference algorithm makes provision for anonymous functions in the first phase (§7.5.2.1). The parameter and return types of the anonymous function are known, so an explicit parameter type inference can be made, and a correspondense is thereby made between the types in the anonymous function (void ?(string)) and the type parameter in the delegate type of the Test method’s parameter (void Action<T>(T)). No algorithm is specified for method groups that would correspond to this algorithm for anonymous functions.

Test((Action<string>)A);

This succeeds, the difference being that the untyped method group parameter A is cast to a type, thereby allowing the type inference of Test to proceed normally with an expression of a particular type as the only argument to the method.

I can think of no reason in theory why overload resolution could not be attempted on the method group A. Then—if a single best binding is found—the method group could be given the same treatment as an anonymous function. This is especially true in cases like this where the method group contains exactly one candidate and it has no type parameters. But the reason it does not work in C#4 appears to be the fact that this feature was not designed and implemented. Given the complexity of this feature, the narowness of its application, and the existance of three easy work-arounds, I am not going to be holding my breath for it!

这篇关于为什么不能C#从这个看似简单的,明显的案例推断类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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