c# - 为什么 .NET List Sort() 不采用显式声明的委托(delegate)对象?

标签 c# sorting generics delegates

快速提问。

this documentation page 上的第二个例子中(第二个代码块,具有一个名为 CompareDinosByLength 的方法),Sort 方法是这样调用的:

dinosaurs.Sort(CompareDinosByLength);

为什么 Sort 方法不需要显式声明的委托(delegate),正如我通过阅读委托(delegate)文档所想到的那样?在我找到那个例子之前,我试图这样做:

delegate int CompareDinosDel(string first, string second);
CompareDinosDel newDel = CompareDinosByLength;
dinosaurs.Sort(newDel);

但我不断收到与委托(delegate)/委托(delegate)方法相关的错误,这些错误不是正确的比较器。

不应该两者都起作用吗?

最佳答案

Why is it that the Sort method didn't need an explicitly declared delegate?

C# 允许一个方法组——也就是说,一个没有(...) 的方法。调用它的参数列表——在需要委托(delegate)的上下文中使用。编译器对方法组执行重载解析就好像该方法组是用委托(delegate)形式参数类型的参数调用的。这决定了应该使用方法组中的哪个方法来创建委托(delegate)。

当方法组正在对作为泛型方法的形式参数类型的委托(delegate)类型进行重载解析时,此重载解析过程有时会导致涉及方法类型推断的异常情况; Sort , 幸运的是不是通用方法,所以这些奇怪的事情不会发挥作用。

此功能已添加到 C# 2.0;在此之前,必须通过

将方法组转换为委托(delegate)
new MyDelegate(MyMethod)

I keep getting errors related to the delegate / delegate method not being proper Comparers. Shouldn't both work?

不幸的是,没有。 C# 在委托(delegate)类型上没有结构标识。即:

delegate void Foo();
delegate void Bar();
...
Foo foo = ()=>{};
Bar bar = foo; // ERROR!

尽管FooBar 在结构上相同,编译器不允许转换。但是,您可以使用之前的技巧:

Bar bar = foo.Invoke;

这相当于

Bar bar = new Bar(foo.Invoke);

但是新bar具有调用 foo 的操作;它通过一个间接级别。

这个功能确实有一定意义。

原因一:

您不希望结构标识在其他地方起作用:

struct Point { int x; int y; ... }
struct Pair { int key; int value; ... }
....
Point point = whatever;
Pair pair = point; // ERROR

原因二:

你可能想说:

delegate int PureMethod(int); 

并且有一个约定PureMethod委托(delegate)是“纯”的——也就是说,它们所委托(delegate)的方法不会抛出,总是返回,返回一个仅根据它们的参数计算得出的值,并且不会产生副作用。应该说是错误的

Func<int, int> f = x => { Console.WriteLine(x); return x+1; };
PureMethod p = f;

因为 f不纯。

然而事后看来,人们实际上并没有制造充满语义的委托(delegate)。 Predicate<int> 类型的值是一个痛点不能分配给 Func<int, bool> 类型的变量反之亦然。

如果我们不得不重新来过,我怀疑委托(delegate)在 CLR 中会有结构标识。

最后,我注意到 VB 对于相互分配混合委托(delegate)类型更为宽容;如果需要,它会自动构建一个适配器委托(delegate)。这可能会让人感到困惑,因为有时看起来引用身份得到了维护,而实际上并没有,但这符合 VB 的“让我的代码正常工作”的理念。

关于c# - 为什么 .NET List Sort() 不采用显式声明的委托(delegate)对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23685227/

相关文章:

c# - 文件路径是url吗?

c# - Process.GetProcesses() 并按内存使用情况排序

php - 从当前日期开始按升序排列对象集合

sorting - 分区排序和快速排序有什么区别?

java - Java 中的有界通配符

swift - 如何在 Swift 的新结果类型中正确使用泛型类型?

java - 构造泛型类的新实例

c# - 使用 C# 将时间跨度值转换为格式 "hh:mm Am/Pm"

c# - null 和 System.DBNull.Value 之间有什么区别?

c# - WinForms TPL Pattern w/Multiple Tasks & UI Sync - 这是正确的吗?