mjg*_*py3 14 c# types anonymous-function unification
我发现自己一直想通过一个Func在地方的一个回报,没有输入Action,例如
Func<int> DoSomething = ...;
Task.Run(DoSomething);
Run Code Online (Sandbox Code Playgroud)
在哪里,我真的不在乎的回报价值DoSomething.
但是,这些类型并不统一,我最终包装了这个调用
Task.Run(() => { DoSomething(); });
Run Code Online (Sandbox Code Playgroud)
有没有办法让这些类型统一而不包装?另外,有没有很好的设计理由为什么他们不统一?
您希望以下语句为真:
如果我有
Func<T>,我应该能够在Action需要的地方使用它.
这将要求Func<T>是(A)分配给Action或(B)隐式转换为Action.
如果我们假设(A)需要T,可以是任何类型,可分配给void.
Eric Lippert在他的博客中回答了这个问题:
不应该"作废"被认为是所有可能的类型协变返回类型转换的方法,从群体之目的,委托类型的超类型?
他的回答是"不",因为这最终与CLI规范不兼容.该CLI规范要求返回值进入堆叠,所以void功能没有最终产生,而那些做返回的东西"啪"的指令,就产生一个"流行"的指令.如果某种方法有一个"动作"可能包含一个void函数或一个返回某些东西的函数,这在编译时是不知道的,编译器就不会知道是否生成"pop"指令.
他接着说:
如果CLI规范说"任何函数的返回值都传递回'虚拟寄存器'"而不是将其压入堆栈,那么我们就可以使返回的void委托与返回任何函数的函数兼容.您始终可以忽略寄存器中的值.但这不是CLI指定的,所以这不是我们能做的.
换句话说,如果存在这个"虚拟寄存器",其中存储了函数的返回值(可能在CLI规范中不存在),C#的编写者及其编译器可能已经完成了你想要的,但是他们不能他们不能偏离CLI规范.
如果我们假设(B),那么就会有一个突破性的变化,正如Eric Lippert在这个博客中解释的那样.从他的博客这个适应的例子中,如果有一个隐式转换从Func<T>到Action,某些程序可能不会编译了该用于(重大更改).该方案目前编译,但尝试取消注释隐式转换操作符,类似于你会问了,它不会编译.
public class FutureAction
{
public FutureAction(FutureAction action)
{
}
//public static implicit operator FutureAction(Func<int> f)
//{
// return new FutureAction(null);
//}
public static void OverloadedMethod(Func<FutureAction, FutureAction> a)
{
}
public static void OverloadedMethod(Func<Func<int>, FutureAction> a)
{
}
public static void UserCode()
{
OverloadedMethod(a => new FutureAction(a));
}
}
Run Code Online (Sandbox Code Playgroud)
(显然,这不是他们正在做的事情,因为这只适用于Func<int>而不是Func<T>,但它说明了问题.)
摘要
我认为你面临的问题是CLI规范的一个工件,当时可能并不是很好,而且我猜他们不想引入重大改变以允许隐式转换才能正常工作.
| 归档时间: |
|
| 查看次数: |
344 次 |
| 最近记录: |