为什么具有返回类型的方法不能与返回 void 的相同签名的委托匹配

本文关键字:返回 返回类型 方法 不能 为什么 void | 更新日期: 2023-09-27 18:31:58

我对C#委托的这种限制相当好奇。 取以下代码,它不会编译:

class Program
{
   delegate void Foo(string s);
   static void Main(string[] args)
   {
      Foo f = Test; // Error
      f("Hello");
   }
   static int Test(string s)
   {
      return s.Length;
   }
}

这里的错误是委托Foo没有返回类型,因此不能用于创建对函数Test的引用。

但是,为什么这是一个问题? 显然,如果通过委托f调用Test,他们将无法访问Test的返回值,这是完全公平的,但在我看来,编译器仍然可以通过简单地忽略返回值来生成类型安全代码,甚至可能能够优化这种情况。

显然,如果情况逆转,Foo指定string返回并Test返回void,我们就会遇到问题。 因此,我完全同意这种情况应该导致编译器错误。 但是,为什么int Test(string)不能隐式匹配委托void Foo(string)

我正在寻找两个可能的答案之一:第一,允许这种能力的逻辑问题。 是否存在通过委托调用方法时忽略返回类型会导致不安全情况的情况? 或者,两个,对 C# 规范的引用,阐明此实现违反规范的原因。

为什么具有返回类型的方法不能与返回 void 的相同签名的委托匹配

C# 规范(第 15.2 节委托兼容性)是这样说的。

方法或委托 M 与委托类型 D 兼容,如果所有 以下情况为真:

· 标识或隐式引用转换存在于 将 M 的类型返回为 D 的返回类型。

任何类型和 void 之间都没有这种转换,因此根据规范不应允许这样做。

我不确定它很可能在逻辑上可以完成,但与其他功能相比,它可能没有足够大的用例。自己创建一个包装器也相当容易,这也减少了用例的需求。

public Action Ignore<T>(Func<T> call)
{
    return () => call();
}