C#3.0通用类型推理过委托作为一个功能参数
-
03-07-2019 - |
题
我想知道为什么C#3.0编译器,是无法推断这种类型的方法时,它是作为一个参数一般功能时,它可以隐含地创建一个代表相同的方法。
这里是一个例子:
class Test
{
static void foo(int x) { }
static void bar<T>(Action<T> f) { }
static void test()
{
Action<int> f = foo; // I can do this
bar(f); // and then do this
bar(foo); // but this does not work
}
}
我认为我将能够通过 foo
要 bar
并已编译器推断的类型 Action<T>
从签名的功能正在传递但是,这不起作用。但是我可以创建一个 Action<int>
从 foo
不铸因此,是否有一个合法的原因,编译器不能也做同样的事情,通过类推理?
解决方案
也许这将使它更清楚:
public class SomeClass
{
static void foo(int x) { }
static void foo(string s) { }
static void bar<T>(Action<T> f){}
static void barz(Action<int> f) { }
static void test()
{
Action<int> f = foo;
bar(f);
barz(foo);
bar(foo);
//these help the compiler to know which types to use
bar<int>(foo);
bar( (int i) => foo(i));
}
}
foo不是一个行动-foo方法小组。
- 在分配发言时,编译器可以清楚地告诉其foo你在谈论,由于int类型的规定。
- 在barz(foo)发言时,编译器可以告诉其foo你在谈论,由于int类型的规定。
- 在酒吧(foo)发言,它可能是任何foo与一个单一的参数-所以编译器放弃。
编辑:我已经增加了两个(多个)的方式帮助编译器找出类型(即如何跳过推断步骤)。
从我读的文章在JSkeet的答复,决定不能推断出该种类型似乎是基于相互infering方案,例如
static void foo<T>(T x) { }
static void bar<T>(Action<T> f) { }
static void test()
{
bar(foo); //wut's T?
}
由于一般的问题是unsolve能,他们选择留的具体问题在那里解决存在的没有解决。
作为一个的后果,这个决定,你不会添加一个载的方法和获取一个整体很多类型的混乱从所有来电者所使用的单个成员的方法小组。我想这是一件好事。
其他提示
理由是,如果类型扩大,那么就不应该失败。即,如果方法foo(string)被添加到类型中,它应该对现有代码无关紧要 - 只要现有方法的内容不会改变。
因此,即使只有一个方法foo,也不能将对foo(称为方法组)的引用强制转换为非类型特定的委托,例如Action<T>
但仅限于类型 - 特定代表,例如Action<int>
。
那是有点奇怪,是的。C#3.0规范的类型推理是难于阅读和具有错误,在它,但是它 看起来 像应该的工作。在第一阶段(第7.4.2.1)我相信有一个错误-这不应该提及方法组中的第一颗子弹(如他们并不涵盖通过明确的参数类型的推断(7.4.2.7),这意味着它应该使用的输出类型推理(7.4.2.6).那 看起来 像应该的工作-但是显然它并不:(
我知道MS是寻求提高规格的类型推断,因此它可能会变得有点更加清晰。我也知道,无论困难,有限制的方法团体和类型推理的限制,这可能是特别的-套管当方法组是唯一实际上是一个单一的方法,不可否认.
埃里克利珀特有的博客上 回型推断不与工作方法团体 这是 类似的 这种情况下-但在这里我们不感兴趣返回的类型,只有在参数类型。这有可能是 其他员额在他类型推理的系列 可以帮助虽然。
请记住作业
Action<int> f = foo;
已经有很多语法糖。编译器实际上为此语句生成代码:
Action<int> f = new Action<int>(foo);
相应的方法调用编译没有问题:
bar(new Action<int>(foo));
Fwiw,帮助编译器推断类型参数也是如此:
bar<int>(foo);
所以归结为问题,为什么赋值语句中的糖而不是方法调用中的糖?我不得不猜测这是因为糖在分配中是明确的,只有一种可能的替代品。但是在方法调用的情况下,编译器编写者已经不得不处理重载解决问题。其规则非常详细。他们可能只是没有解决它。
为了完整起见,这不是特定于C#:相同的VB.NET代码同样失败:
Imports System
Module Test
Sub foo(ByVal x As integer)
End Sub
Sub bar(Of T)(ByVal f As Action(Of T))
End Sub
Sub Main()
Dim f As Action(Of integer) = AddressOf foo ' I can do this
bar(f) ' and then do this
bar(AddressOf foo) ' but this does not work
End Sub
End Module
错误BC32050:无法推断出'Public Sub bar(Of T)的类型参数'T'(f As System.Action(Of T))'。