C#语言不需要委托的概念吗? [关闭]
Posted
技术标签:
【中文标题】C#语言不需要委托的概念吗? [关闭]【英文标题】:C# language doesn't need the concept of delegates? [closed] 【发布时间】:2015-06-03 08:48:09 【问题描述】:感谢您的客观性,尤其是在 C# 是您选择的语言的情况下。愤怒的投票者,我想我在这里问了一个合理的问题?否则请留下建设性意见。
问题...
C++ 允许简单地传递(通用)函数指针,如下所示:How to pass a generic function pointer as parameter Java 为此使用接口 - 从 OO 的角度来看也是优雅的,我们只使用基本语言已经提供的东西。但是,我从未见过将 delegate
设为显式概念/关键字的任何真正优势,而不是像 C++ 或 Java 那样仅管理回调的概念——将函数指针视为另一个现有类型系统下的情况。 (PS 是的,C# 泛型与 C++ 泛型不同,而 Java 具有运行时而不是编译时泛型,但你明白我的意思)。
(抛开所有的傲慢和教条不谈)为什么 C# 的设计者认为给一个通用的、现有的编程概念起一个新名称是合适的,该概念可以称为通用函数指针/回调?如果没有这样的概念,在 C# 中代表不能更简单地表示吗?
免责声明我已经查看了很多关于 *** 的答案,但没有一个能够令人满意地回答为什么设计师认为包含另一个关键字来处理回调处理这样基本的事情。
【问题讨论】:
好吧,对于初学者来说,一个委托可以引用多个函数(参见多播委托)。所以称它为函数指针是不准确的 我认为关键在于委托是类型安全的:“委托就像 C++ 函数指针,但是是类型安全的。” - msdn.microsoft.com/en-us/library/ms173171.aspx @ArcaneEngineer 请注意,delegate
关键字是 C# 的语法糖。在 IL 代码中(因此在“.NET”中),delegate
s 只是 MulticastDelegate
的子类(即 Delegate
的子类),带有带有“正确”签名的 Invoke()
方法,因此它们是相似的到Java“缺少”“委托”(这是具有单个方法的接口)。然后由 CLR 处理 Invoke()
方法
@xanatos 仍然涉及到相当多的 CLR 魔法,如果他们使用单一方法接口,例如 java,则不需要。
委托实际上是扩展System.MulticastDelegate
的类,另外还提供BeginInvoke()
、EndInvoke()
和Invoke()
方法。所以它们不仅仅是简单的函数指针。
【参考方案1】:
C++ 有来自 C++11 (std::function
) 的“官方”(非 Boost)“完整”代表......在此之前,获取指向成员函数的指针总是有点 hackish......所以我不会认为 C++ 是一个很好的比较 :-) 并且 C++ 可以重载圆括号,因此更容易“隐藏”需要完成的 hack,并为程序员提供一种“简单”的使用方式std::function
.
现在...Java...要“纠正”(但假设这不是一个遗漏,而是一个经过计算的决定,因此他们没有任何要纠正的东西)他们首先必须引入的缺失委托概念Java 1.1 中的匿名类,然后在 Java 8 中,它们引入了函数式接口(作为非 Java 程序员,我认为最后一件事有点骇人听闻……元描述接口具有单个方法,然后在编译时间...我不太喜欢它...)。这是因为否则所需的样板代码非常多......
让我们从简单的开始...IComparer<>
接口...它是一个具有单一方法的接口,因此它与委托非常相似...
一个简单的实现:
public class MyComparer : IComparer<int>
public int Compare(int x, int y)
return x.CompareTo(y);
这里有一个样板行,第一个 (public class MyComparer : IComparer<int>
)。通过引入 C#delegate
,您已经为每次使用委托获得了一行...但是等等!假设您的“代表”需要对“包含”它的类的引用...
public class MyComparer : IComparer<int>
public MyClass Target;
public int Compare(int x, int y)
return Target.Ascending ? x.CompareTo(y) : y.CompareTo(x);
现在这个类需要是MyClass
的嵌套类。请注意,我对嵌套类没有任何意见...
我们添加了一个新行 (public MyClass Target
)...但是这段代码通常写错了...您不应该有公共的非只读字段。您可以使用自动属性public MyClass Target get; set;
,但这也是 C# 3.0 中引入的同步糖......没有它们,样板代码会增长......我更愿意有一个private readonly MyClass Target
.. 但我会为构造函数添加四行...您要我为委托写多少行? :-)
C#/.NET 委托仍然提供更大的灵活性:您使用的函数可以有任何名称,因此您可以在同一个类中拥有多个...MyComparer
可以实现为两种方法:
public int CompareAscending(int x, int y)
和
public int CompareDescending(int x, int y)
无需添加太多代码,或将所有内容拆分为多个(嵌套)类。
【讨论】:
我不认为这是决定性的(还没有?),但这是值得思考的好东西(以及您的 cmets)。我正在消化。 只是补充一点,回想起来,我确实同意 Java / 接口的事情。我认为不幸的是,Java 和 C# 没有像 C 和 ECMA 语言那样将函数视为一等公民。【参考方案2】:委托不仅仅是一个简单的回调。首先,它适用于静态方法和实例方法,调用者不必处理差异。其次,委托不是单一的方法指针。它可以是一个“指针链”,因此调用者可以通过一次调用调用多个回调——同样,调用者不必担心它是单个调用还是多个调用。 是的,可以从头开始实现相同的机制 - 但可以使用机器代码构建所有内容 - 这需要高级语言。
【讨论】:
谢谢维克多。问题是,它看起来仍然像语法糖,大多数语言设计者并没有轻视增加语言复杂性的影响。循环遍历回调是微不足道的,并且在底层(在 IL 级别),系统仍然必须循环遍历函数指针——显然,你不能一次调用多个函数。 @ArcaneEngineer 考虑到委托是event
s 的基础......(这是 .NET 中的第一级事物)......他们可以将代码从委托移动到事件,但它不会有太大变化......而且事件在 Winforms 中无处不在(那是 .NET 的第一个 UI)
@xanatos 对,现在 that 是相关的。虽然正如你所说,我确实想知道为什么它没有作为event
s 的一部分完成。让我们看看是否有更多的cmets。
@ArcaneEngineer 我要补充一点,所有代表都是MulticastDelegate
并且Delegate
(单个)在任何地方都没有使用,而MulticastDelegate
仅对@ 有意义987654326@(我从来没有在event
之外添加代表......这似乎是非常罕见的事情)似乎表明这种关系在.NET/C#的创造者的头脑中是最重要的
@xanatos 我们知道为什么事件是 C# 中的一流/基本概念吗?因为这可能是这个设计决策的根源。以上是关于C#语言不需要委托的概念吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章