为什么 C# 不允许像 C++ 这样的非成员函数?
C# 不允许编写非成员函数,每个方法都应该是类的一部分。 我认为这是所有 CLI 语言的限制。 但我错了,我发现C++/CLI支持非成员函数。 当它被编译时,编译器将使该方法成为某个未命名类的成员。
以下是 C++/CLI 标准的规定:
[注意:CLI 将非成员函数视为某些未命名类的成员; 但是,在 C++/CLI 源代码中,此类函数无法使用该类名显式限定。 尾注]
元数据中非成员函数的编码未指定。 [注意:这不会导致互操作问题,因为此类函数无法具有公共可见性。 尾注]
所以我的问题是为什么 C# 不实现这样的东西? 或者您认为不应该有非成员函数并且每个方法都应该属于某个类?
我的观点是拥有非成员函数支持,这有助于避免污染类的接口。
有什么想法吗..?
C# will not allow to write non-member functions and every method should be part of a class. I was thinking this as a restriction in all CLI languages. But I was wrong and I found that C++/CLI supports non-member functions. When it is compiled, compiler will make the method as member of some unnamed class.
Here is what C++/CLI standard says,
[Note: Non-member functions are treated by the CLI as members of some unnamed class; however, in C++/CLI source code, such functions cannot be qualified explicitly with that class name. end note]
The encoding of non-member functions in metadata is unspecified. [Note: This does not cause interop problems because such functions cannot have public visibility. end note]
So my question is why don't C# implement something like this? Or do you think there should not be non-member functions and every method should belong to some class?
My opinion is to have non-member function support and it helps to avoid polluting class's interface.
Any thoughts..?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
更新:2009 年的这个问题已经被语言进化所取代。 自 C# 10 以来,该语言已支持类声明之外的顶级语句,从而使“为什么不”问题变得毫无意义。
请参阅此博客文章:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/why-doesnt-c-implement-top-level-methods
以及此后续发布:
http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-脚本语言.aspx
(来自原文的强调)
UPDATE: This question from 2009 has been rather overtaken by language evolution. Since C# 10, the language has supported top-level statements outside of class declarations, rendering the "why not" question nonsensical.
See this blog posting:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/why-doesnt-c-implement-top-level-methods
and this follow-up posting:
http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-scripting-language.aspx
(emphasis from original text)
C# 不允许,因为 Java 不允许。
我可以想到 Java 的设计者可能不允许
正如我在评论中已经说过的,我认为这是这是一个很好的问题,而且在很多情况下,非成员职能会更好。 (这部分主要是对所有其他答案说“你不需要它”的回应)
在允许使用非成员函数的 C++ 中,它们通常是首选,原因如下:
find
函数不需要了解 LinkedList 类即可对其进行操作。 如果它被定义为成员函数,那么它将成为 LinkedList 类的成员,基本上将这两个概念合并为一个大 blob。拥有非成员函数的能力可能起源于 C(在那里你别无选择),但在现代 C++ 中,它本身就是一个重要的功能,不仅是为了向后兼容的目的,而且因为更简单,它允许更干净、更可重用的代码。
事实上,C# 似乎很晚才意识到同样的事情。 您认为为什么要添加扩展方法? 它们试图实现上述目标,同时保留简单的类似 Java 的语法。
Lambda 也是有趣的例子,因为它们本质上也是自由定义的小函数,而不是任何特定类的成员。 所以,是的,非成员函数的概念很有用,C# 的设计者也意识到了同样的事情。 他们只是试图从后门偷偷地引入这个概念。
http://www.ddj.com/cpp/184401197 和 http://www.gotw.ca/publications/mill02.htm 是 C++ 专家就该主题撰写的两篇文章。
C# doesn't allow it because Java didn't allow it.
I can think of several reasons why the designers of Java probably didn't allow it
As I already said in comments, I think this is a good question, and there are plenty of cases where non-member functions would've been preferable. (this part is mostly a response to all the other answers saying "you don't need it")
In C++, where non-member functions are allowed, they are often preferred, for several reasons:
std::find
or std::sort` as non-member functions, so that they can be reused on any type of sequences, whether it is arrays, sets, linked lists or (for std::find, at least) streams. Code reuse is also an important part of OOP.find
function doesn't need to know about the LinkedList class in order to be able to work on it. If it had been defined as a member function, it would be a member of the LinkedList class, basically merging the two concepts into one big blob.The ability to have non-member functions may have originated with C (where you had no other choice), but in modern C++, it is a vital feature in its own right, not just for backward-comparibility purposes, but because of the simpler, cleaner and more reusable code it allows.
In fact, C# seems to have realized much the same things, much later. Why do you think extension methods were added? They are an attempt at achieving the above, while preserving the simple Java-like syntax.
Lambdas are also interesting examples, as they too are essentially small functions defined freely, not as members of any particular class. So yes, the concept of non-member functions is useful, and C#'s designers have realized the same thing. They've just tried to sneak the concept in through the back door.
http://www.ddj.com/cpp/184401197 and http://www.gotw.ca/publications/mill02.htm are two articles written by C++ experts on the subject.
非成员函数是一件好事因为它们改进了封装并减少了类型之间的耦合。 大多数现代编程语言(例如 Haskell 和 F#)都支持自由函数。
Non member functions are a good thing because they improve encapsulation and reduce coupling between types. Most modern programming languages such as Haskell and F# support free functions.
不将每个方法放入命名类中有什么好处? 为什么非成员函数会“污染”类的接口? 如果您不希望它作为类的公共 API 的一部分,请不要将其公开或不要将其放入该类中。 您始终可以创建不同的类。
我不记得曾经想要编写一个没有适当范围的浮动方法 - 当然,除了匿名函数(它们实际上并不相同)。
简而言之,我看不到非成员函数有任何好处,但我可以看到将所有方法放入适当命名的类中在一致性、命名和文档方面的好处。
What's the benefit of not putting each method in a named class? Why would a non-member function "pollute" the class's interface? If you don't want it as part of the public API of a class, either don't make it public or don't put it in that class. You can always create a different class.
I can't remember ever wanting to write a method floating around with no appropriate scope - other than anonymous functions, of course (which aren't really the same).
In short, I can't see any benefit in non-member functions, but I can see benefits in terms of consistency, naming and documentation in putting all methods in an appropriately named class.
CLS(公共语言规范)规定,符合 CLS 的库中不应包含非成员函数。 它就像是除了 CLI(公共语言界面)的基本限制之外的一组额外的限制。
C# 的未来版本可能会添加编写
using
指令的功能,该指令允许在没有类名限定的情况下访问类的静态成员:这样就无需进行更改CLS 和现有库。
这些博客文章演示了一个用于 C# 函数式编程的库,它们使用只有一个字母长的类名,以尝试减少由于限定静态方法调用的要求而引起的噪音。 如果
using
指令可以针对类,这样的示例会变得更好一些。The CLS (common language specification) says that you shouldn't have non-member functions in a library that conforms to the CLS. It's like an extra set of restrictions in addition to the basic restrictions of the CLI (common language interface).
It is possible that a future version of C# will add the ability to write a
using
directive that allows the static members of a class to be accessed without the class name qualification:Then there will be no need to change the CLS and existing libraries.
These blog posts demonstrate a library for functional programming in C#, and they use a class name that is just one letter long, to try and cut down the noise caused by the requirement to qualify static method calls. Examples like that would be made a little nicer if
using
directives could target classes.自 Java 以来,大多数程序员很容易接受任何方法都是类的成员。 我没有制造任何相当大的障碍,也没有使方法的概念变得更加狭窄,这使得语言变得更容易。
然而,事实上,类推断对象,对象推断状态,因此类仅包含静态方法的概念看起来有点荒谬。
Since Java, most programmers have easily accepted that any method is a member of a class. I doesn't make any considerable obstacles and make the concept of method more narrow, which make a language easier.
However, indeed, class infers object, and object infers state, so the concept of class containing only static methods looks a little absurd.
我认为您确实需要澄清您希望创建非成员静态方法来实现什么。
例如,您可能需要它们执行的某些操作可以使用 扩展方法 来处理
另一个典型的用途(仅包含静态方法的类)是在库中。 在这种情况下,在完全由静态方法组成的程序集中创建一个类没有什么坏处。 它将它们保持在一起,避免命名冲突。 毕竟,Math 中存在具有相同目的的静态方法。
另外,您不必将 C++ 的对象模型与 C# 进行比较。 C++ 很大程度上(但不是完全)与 C 兼容,而 C 根本没有类系统 - 因此 C++ 必须支持这种 C 遗留的编程习惯,而不是为了任何特定的设计命令。
I think you really need to clarify what you would want to create non-member static methods to achieve.
For instance, some of the things you might want them for could be handled with Extension Methods
Another typical use (of a class which only contains static methods) is in a library. In this case, there is little harm in creating a class in an assembly which is entirely composed of static methods. It keeps them together, avoids naming collisions. After all, there are static methods in Math which serve the same purpose.
Also, you should not necessarily compare C++'s object model with C#. C++ is largely (but not perfectly) compatible with C, which didn't have a class system at all - so C++ had to support this programming idiom out of the C legacy, not for any particular design imperative.
看,其他编程语言很难从编译器的角度定义函数实例的内部性质。 在 Pascal 和 C 中,实例基本上被定义为只能作为指针处理的东西。 特别是,因为读/写可执行代码位置是九分之七的计算机科学教授坚决反对的。 作为类的成员,没有人需要关心如何对待其表现形式,因为该表现形式的类型是从类属性派生的。 可以创建像全局函数一样精确处理的东西:分配给变量的 lambda 函数:
<代码>
. And it can simply be called like a global function by its variable name.
If so, the difference would be implementing a new object type on the lowest level with same behavior as another one. That is considered bad practice by experienced programmers, and was perhaps scrapped because of this.
Look, other programming languages have a hard time to define the internal nature of a function instance from the compiler's point of view. In Pascal and C, the instances are basically defined as something that can be processed as pointer only. Especially, since reading/writing to executable code positions is what 7 out of 9 computer science professors are dead set against. As member of a class, no one does need to care how to treat its manifestation because this manifestation's type is derived from a class property. It is possible to create something that is exactly processed like a global function: a lambda function, assigned to a variable:
. And it can simply be called like a global function by its variable name.
If so, the difference would be implementing a new object type on the lowest level with same behavior as another one. That is considered bad practice by experienced programmers, and was perhaps scrapped because of this.
请记住:C++ 是一种比 C# 复杂得多的语言。 尽管它们在语法上可能相似,但在语义上它们是非常不同的野兽。 你不会认为做出这样的改变会非常困难,但我可以看到它会怎样。 ANTLR 有一个很好的 wiki 页面,名为 是什么让语言问题变得困难? 对于此类问题,最好咨询一下。 在这种情况下:
现在,我们不仅要担心类中定义的函数,还必须担心类外部定义的函数。 从概念上讲,没有太大区别。 但是在词法分析和解析代码方面,现在您遇到了一个额外的问题,即必须说“如果函数在类外部,则它属于这个未命名的类。但是,如果它在类内部,则它属于那个未命名的类”班级。”
另外,如果编译器遇到这样的方法:
...它现在必须回答“Bar 是位于此类中还是全局类?”的问题。
这是导致问题的另一件事。 请记住,C# 不需要前向声明。 编译器将进行一次检查以确定哪些类被命名以及这些类包含哪些函数。 现在您必须担心查找类和函数,其中函数可以位于类内部或外部。 这是 C++ 解析器不必担心的事情,因为它会按顺序解析所有内容。
现在不要误会我的意思,它可能可以用 C# 完成,而且我可能会使用这样的功能。 但是,当您只需在静态方法前面键入类名时,真的值得克服这些障碍吗?
Bear something in mind: C++ is a much more complicated language than C#. And although they may be similiar syntactically, they are very different beasts semantically. You wouldn't think it would be terribly difficult to make a change like this, but I could see how it could be. ANTLR has a good wiki page called What makes a language problem hard? that's good to consult for questions like this. In this case:
Now instead of just worrying about functions defined in classes, we have to worry about functions defined outside classes. Conceptually, there isn't much difference. But in terms of lexing and parsing the code, now you have the added problem of having to say "if a function is outside a class, it belongs to this unnamed class. However, if it is inside the class, then it belongs to that class."
Also, if the compiler comes across a method like this:
...it now has to answer the question "is Bar located within this class or is it a global class?"
This is another thing that causes problems. Remember that C# doesn't require forward declarations. The compiler will make one pass just to determine what classes are named and what functions those classes contain. Now you have to worry about finding classes and functions where functions can be either inside or outside of a class. This is something a C++ parser doesn't have to worry about as it parses everything in order.
Now don't get me wrong, it could probably be done in C#, and I would probably use such a feature. But is it really worth all the trouble of overcoming these obstacles when you could just type a class name in front of a static method?
如果将自由函数与鸭子类型结合起来,它们将非常有用。 整个C++ STL都是基于它的。 因此,我确信 C# 在设法添加真正的泛型时将引入自由函数。
与经济学一样,语言设计也与心理学有关。 如果您通过 C# 中的自由函数激发了对真正泛型的兴趣而不交付,那么您就会杀死 C#。 然后,所有 C# 开发人员都会转向 C++,但没有人希望这种情况发生,C# 社区也不希望,更肯定那些投资于 C++ 的人也不希望这种情况发生。
Free functions are very useful if you combine them with duck typing. The whole C++ STL is based on it. Hence I am sure that C# will introduce free functions when they manage to add true generics.
Like economics, language design is also about psychology. If you create appetite for true generics via free functions in C# and not deliver, then you would kill C#. Then all C# developers would move to C++ and nobody wants that to happen, not the C# community and most certainly not those invested in C++.
虽然您确实需要一个类(例如名为
FreeFunctions
的静态类)来保存此类函数,但您可以自由地将using static FreeFunctions;
放置在任何文件的顶部需要其中的函数,而不必在代码中添加FreeFunctions.
限定符。我不确定是否确实存在这种情况明显不如不要求函数定义包含在类中的情况。
While it's true you need a class (e.g. a static class called
FreeFunctions
) to hold such functions, you're free to placeusing static FreeFunctions;
at the top of any file that needs the functions from it, without having to litter your code withFreeFunctions.
qualifiers.I'm not sure if there's actually a case where this is demonstrably inferior to not requiring the function definitions to be contained in a class.
Csharp 没有非成员函数,因为它复制或受到 java 哲学的启发,即只有 OOP 才能解决所有问题,并且它只允许使用 OO 方式解决问题。
如果我们真的想做泛型编程,非成员函数是非常重要的功能。 与将它们放在一个类中相比,它们更具可重用性。
由于缺少非成员函数,CSharp 必须提出 ExtensionMethods。
现在编程语言正在向函数式编程范式发展,它似乎是处理和解决问题的更好方法,也是未来。 CSharp 应该重新考虑一下。
Csharp does not have non-member function because it has copied or inspired by java's philosophy that only OOPs is the solution for all the problems and it will only allow things to be solved using OO way.
Non-member functions are very important feature if we really want to do generic programming. They are more reusable compared to putting them in a class.
CSharp has to come up with ExtensionMethods due to absence of non-member functions.
As now programming languages are moving towards functional programming paradigm and it seems to be the better way to approach and solve the problem and is the future. CSharp should rethink about it.