为什么不能将 Action<Object> 委托用作线程池的 WaitCallback?
Why can't an Action<Object> delegate be used as a WaitCallback for Threadpool?
代表 WaitCallback
和 Action<Object>
共享相同的签名。尽管如此,正如下面的代码所证明的,它们不能被视为同一类型。
static void Main(string[] args)
{
WaitCallback wcb = (o) => Console.WriteLine("Hello from wcb delegate");
ThreadPool.QueueUserWorkItem(wcb);//works
Action<object> action = (o) => Console.WriteLine("Hello from action<object> delegate");
ThreadPool.QueueUserWorkItem(action);//does not compile: Cannot convert from Action<object> to WaitCallback
Console.ReadLine();
}
关于这个观察我有两个问题:
为什么签名相同但名称不同的代表不属于同一类型?语言设计团队是否会选择不同的选择,或者会导致不一致或其他问题?
当在 .NET Framework 2.0 中引入 Action
委托时,WaitCallback
已经存在。我想知道是否不是这种情况,是否有理由引入额外的委托类型 WaitCallback
而不是使用 Action
?
从类型系统的角度来看,WaitCallback
与 Action<object>
是不同的类型,它们之间不存在隐式转换。因此,您不能在需要 WaitCallback
的地方使用 Action<object>
。然而,实际的 方法 被引用并用作委托,只关心它们的参数列表和 return 类型的兼容性,所以你可以 [=25= 而不是匿名方法]
private void Foo(object o) {
Console.WriteLine("Hello from actual method");
}
下面几行可以正常工作:
WaitCallback wcb = Foo;
Action<object> action = Foo;
ThreadPool.QueueUserWorkItem(Foo);
请注意,在这种情况下,方法的 name 用于引用它,其解析和处理方式与将特定类型的变量传递给方法完全不同。对于后者,您完全受实际类型的支配,它们的转换和委托绝不是特殊的。
规范还包含以下注释:
Delegate types in C# are name equivalent, not structurally equivalent. Specifically, two different delegate types that have the same parameter lists and return type are considered different delegate types.
(警告:猜测;我不在语言设计团队) 所以这是一个有意识的选择,考虑到我上面写的,这可能不是不可能的允许您请求的内容,但这将是重载解析工作方式的一个主要例外。所以我猜这个电话是为了简化语言。此外,在 C# 1 时代,实际上结构兼容的委托可能并不多。
至于你的第二点,在那种情况下他们可能会选择 Action
。例如,请参阅 Task.Run
方法,它采用 Action
而不是自定义委托。对于不采用或采用一个参数的操作,似乎很明显不引入新委托类型的情况。但是,对于 Action<string, string, int, double>
或等效的 Func
类型,我猜想拥有一个可以记录的实际命名类型将比使用通用 Action
或 Func
类型好得多。
代表 WaitCallback
和 Action<Object>
共享相同的签名。尽管如此,正如下面的代码所证明的,它们不能被视为同一类型。
static void Main(string[] args)
{
WaitCallback wcb = (o) => Console.WriteLine("Hello from wcb delegate");
ThreadPool.QueueUserWorkItem(wcb);//works
Action<object> action = (o) => Console.WriteLine("Hello from action<object> delegate");
ThreadPool.QueueUserWorkItem(action);//does not compile: Cannot convert from Action<object> to WaitCallback
Console.ReadLine();
}
关于这个观察我有两个问题:
为什么签名相同但名称不同的代表不属于同一类型?语言设计团队是否会选择不同的选择,或者会导致不一致或其他问题?
当在 .NET Framework 2.0 中引入
Action
委托时,WaitCallback
已经存在。我想知道是否不是这种情况,是否有理由引入额外的委托类型WaitCallback
而不是使用Action
?
从类型系统的角度来看,WaitCallback
与 Action<object>
是不同的类型,它们之间不存在隐式转换。因此,您不能在需要 WaitCallback
的地方使用 Action<object>
。然而,实际的 方法 被引用并用作委托,只关心它们的参数列表和 return 类型的兼容性,所以你可以 [=25= 而不是匿名方法]
private void Foo(object o) {
Console.WriteLine("Hello from actual method");
}
下面几行可以正常工作:
WaitCallback wcb = Foo;
Action<object> action = Foo;
ThreadPool.QueueUserWorkItem(Foo);
请注意,在这种情况下,方法的 name 用于引用它,其解析和处理方式与将特定类型的变量传递给方法完全不同。对于后者,您完全受实际类型的支配,它们的转换和委托绝不是特殊的。
规范还包含以下注释:
Delegate types in C# are name equivalent, not structurally equivalent. Specifically, two different delegate types that have the same parameter lists and return type are considered different delegate types.
(警告:猜测;我不在语言设计团队) 所以这是一个有意识的选择,考虑到我上面写的,这可能不是不可能的允许您请求的内容,但这将是重载解析工作方式的一个主要例外。所以我猜这个电话是为了简化语言。此外,在 C# 1 时代,实际上结构兼容的委托可能并不多。
至于你的第二点,在那种情况下他们可能会选择 Action
。例如,请参阅 Task.Run
方法,它采用 Action
而不是自定义委托。对于不采用或采用一个参数的操作,似乎很明显不引入新委托类型的情况。但是,对于 Action<string, string, int, double>
或等效的 Func
类型,我猜想拥有一个可以记录的实际命名类型将比使用通用 Action
或 Func
类型好得多。