方法组(C#深度)-需要帮助更好地理解什么是方法组

10
我已阅读若干与“什么是方法组”相关的StackOverflow问题和其他互联网文章,它们都在底线上说了同样的话 - 方法组是“一组重载方法”。然而,在Jon Skeet的《C#深入(第二版)》中(第9.4.1章节),他在Lambda表达式的上下文中陈述了有关方法组的以下措辞:
"改变的原因:简化通用方法调用 类型推断发生在一些情况下。我们已经看到它应用于隐式类型数组, 当你尝试将方法组隐式转换为委托类型时,也需要类型推断。 当你使用一个方法组作为另一个方法的参数时,这可能特别令人困惑: 随着被调用方法的重载和方法组内部的方法的重载以及泛型方法的可能性加入, 潜在转换的集合可能是巨大的。”
方法组不仅仅是一组重载方法,或者他在说你实际上可以创建一个保留整个方法组的委托。或者是我没有完全理解的完全不同的东西。
有人能解释一下他在这里陈述的可能性吗?
谢谢,

7
@等待JonSkeet本人更好地解释,他在SO上.. :) (该句话的意思是建议等待JonSkeet本人在Stack Overflow上进行更好的解释。) - Shekhar_Pro
3个回答

15
Jon所描述的场景如下:
int M() {...}
string M<T>(T t) {...}
double M<T>(List<T> t) {...} 
static void M(double d) {...}
... etc ...

void N(Func<int> f) {...}
void N<T>(Action<T> a) {...}
void N<T>(Func<IEnumerable<T>> f) {...}
... etc ...

N(M);

N和M都是方法组,包含潜在的几十个方法,其中一些可能是泛型方法。编译器需要解决的问题是“确定开发人员想要的方法是哪个,并确定如果所需方法是泛型的,则类型参数是什么”。为了完成所有这些工作,编译器必须尝试每个可能的N,然后确定每个可能的M与N重载的形式参数的委托类型兼容。它必须丢弃不起作用的方法,然后从所有剩下的可能的组合中找出一个“最佳”的结果,如果有的话。这是语义分析中的一个相当棘手的问题。

这里有几篇关于这个话题的有趣文章(也许Eric已经忘记了它们:))http://blogs.msdn.com/b/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx - Konstantin Oznobihin

4
方法组是表示一组重载方法的表达式,因此很明显,他在说使用这种表达式创建委托。例如:

class Foo
{
public static void M() {}
public static void M(int _) {}
}
...
Action a = new Action(Foo.M); // 这里Foo.M是一个方法组。

您还可以查看C#规范以获取更详细的信息。
表达式被分类为以下之一:
...
• 方法组,它是从成员查找(§7.4)中得出的一组重载方法。方法组可能具有关联的实例表达式和关联的类型参数列表。当调用实例方法时,评估实例表达式的结果变成了由this表示的实例(§7.6.7)。方法组允许在调用表达式(§7.6.5)、委托创建表达式(§7.6.10.5)和作为is运算符的左操作数中使用,并且可以隐式转换为兼容的委托类型(§6.6)。在任何其他上下文中,将表达式分类为方法组会导致编译时错误。

2

难道他不是在说当您提供方法组作为参数时,很难准确推断您的意思,因为它可能是组内的任何一个方法吗?

考虑到不同的重载具有不同的签名(而泛型方法使方法签名变得更加模糊),如果您只给定方法组作为参数,则很难精确确定参数的类型。


是的,这是我理解的方式。然而,我认为我刚刚明白了,这不是实际上创建一个委托来“整个组” - 但因为方法调用含糊不清,并且有“众多”可能相等的方法 - 它本质上指向“方法组”。 - pghtech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接