为什么C#不容许非成员函数,如C ++为什么C#不容许非成员函数,如C ++(Why C# is n

2019-05-13 14:41发布

C#将不允许写非成员函数和每个方法应该是一个类的一部分。 我想这是所有CLI语言的限制。 可是我错了,我发现C ++ / CLI支持非成员函数。 当它被编译,编译器将会使该方法的一些无名类的成员。

以下是C ++ / CLI标准说

[注:非成员函数由CLI视为一些无名类的成员; 然而,在C ++ / CLI源代码,这样的功能不能被明确地与该类名限定。 注完]

的非成员函数中的元数据的编码是不确定的。 [注:这不会导致互操作性问题,因为这样的功能不能有公众知名度。 注完]

所以我的问题是,为什么不C#实现这样的事情? 或者你觉得不应该有非成员函数和每个方法应该属于某个类?

我的意见是有非成员函数支持,它有助于避免污染类的接口。

有什么想法吗..?

Answer 1:

看到这个博客中:

http://blogs.msdn.com/ericlippert/archive/2009/06/22/why-doesn-tc-implement-top-level-methods.aspx

(......)

我问:“为什么不C#实现功能X?” 每时每刻。 答案总是一样的:因为从来没有人设计的,规定,实施,测试,文档和装运该功能。 这些东西所有六个是必要的,做出特色发生。 所有这些花费的时间,精力和巨额资金。 特点是不便宜的,我们非常努力,以确保我们只运送那些给我们定的限制时间,精力和金钱预算,我们的用户的最佳利益的功能。

我的理解是这样一个普遍的答案可能并不解决具体的问题。

在这种特殊情况下,明确了用户的好处是,在过去没有大到足以证明并发症这将随之而来的语言。 通过stricting内如何相互不同的语言实体鸟巢我们(1)限制的法律的程序是在一个共同的,易于理解的风格,和(2)使人们有可能确定哪些是可以理解,可指定的,可执行的,可检验的“标识符查找”规则且有稽。

通过限制方法机构永远是一个结构或类里面,我们更容易地推理在调用上下文中使用不合格标识的含义; 这样的事情是总是当前类型(或碱型)的可调用构件。

(......)

这个后续发布:

http://blogs.msdn.com/ericlippert/archive/2009/06/24/it-already-is-a-scripting-language.aspx

(......)

像所有的设计决策,当我们面临着一些相互竞争的,引人注目的,有价值的,noncompossible想法,我们必须找到一个可行的折衷办法。 我们不这样做,除了通过考虑所有possibilites,这是我们在这种情况下做什么。

(重点从原文)



Answer 2:

C#不允许它因为Java没有答应。

我能想到的几个原因的Java的设计者可能没有允许它

  • Java是设计简单。 他们试图使语言没有捷径随意,让您通常只有一个简单的方法做的一切,即使其他的办法将是清洁或更简洁。 他们想尽量减少学习曲线,学习“一类可能含有的方法”比“一类可以包含方法和功能可能存在外班”更简单。
  • 从表面上看,它看起来不太面向对象。 (凡是不是一个对象的一部分,显然不能面向对象?可以吗?当然,C ++说是的,但是C ++并没有参与这个决定)

正如我已经在评论中说,我认为这是一个很好的问题,并有大量的地方非成员函数会一直最好的情况下。 (这部分主要是对所有其他的答案说的回应“你不需要它”)

在C ++中,其中非成员函数是允许的,它们通常是优选的,有几个原因:

  • 它有助于封装。 该方法较少有机会获得一类的私有成员,越容易该类将重构或维护。 封装是OOP的一个重要组成部分。
  • 代码可以重复使用时,它不是一类的部分更加容易。 例如,C ++标准库定义std::find或std :: sort`作为非成员函数,使得它们可以在任何类型的序列可以重复使用,无论是数组,集合,链表或(对于STD: :发现,至少)流。 代码重用也是OOP的重要组成部分。
  • 它给了我们更好的去耦。 该find功能并不需要了解LinkedList类,以便能够进行这项工作。 如果它已被定义为一个成员函数,这将是LinkedList类的成员,基本上合并两个概念成为一个大斑点。
  • 可扩展性。 如果你接受一个类的接口不只是“所有的公共成员”,而且还“是在类操作的所有非成员函数”的话,那就可以扩展一个类的接口,而无需修改或还要重新编译类本身。

有非成员函数的能力可能起源与C(在这里你没有其他选择),但在现代C ++中,它是在自己的权利,而不仅仅是向后comparibility而言是至关重要的特征,但由于简单,更清洁,更可重用的代码允许。

事实上,C#似乎很久以后已经意识到了很多同样的事情。 为什么你认为加入扩展方法? 他们是在实现上述,同时保持简单的Java的语法的一种尝试。 lambda表达式也是有趣的例子,因为它们太基本上是小的功能自由定义,而不是作为任何特定类的成员。 所以,是的,非成员函数的概念是有用的,而C#的设计师已经意识到同样的事情。 他们刚刚试图偷看的概念走后门。

http://www.ddj.com/cpp/184401197和http://www.gotw.ca/publications/mill02.htm是由C ++关于这个问题的专家撰写的两篇文章。



Answer 3:

非成员函数是一件好事,因为他们提高封装 ,降低类型之间的耦合。 大多数现代编程语言,如Haskell和F#支持免费功能。



Answer 4:

有什么理由把每种方法在一个名为类的益处? 为什么一个非成员函数“污染”之类的接口? 如果你不希望它作为一类的公共API的一部分,要么不把它公开或者不把它放在类。 你总是可以创建一个不同的类。

我不记得曾经想写左右浮动,没有适当的范围的方法 - 比匿名函数,当然,(这是不是真的一样)等。

总之,我无法看到非成员函数任何好处,但我可以在一致性,命名和文献方面,在把所有方法在适当命名的类见效益。



Answer 5:

该CLS(公共语言规范)说,你不应该有非成员函数在符合CLS的库。 这就像一组额外的除了CLI(通用语言界面)的基本限制的限制。

这可能是C#的未来版本将增加写的能力, using指令,允许无类名的资格要访问类的静态成员:

using System.Linq.Enumerable; // Enumerable is a static class

...

IEnumerable<int> range = Range(1, 10); // finds Enumerable.Range

然后,就没有必要改变CLS和现有的库。

这些博客文章表现出库在C#函数式编程,以及他们使用一个类名,这只是一个字母,以试图降低所引起的需求噪音资格静态方法调用。 这样的例子会做出更好一点,如果using指令能目标类。



Answer 6:

  • 拥有类中的所有代码谎言允许较为强大的一套反射能力。
  • 它允许使用静态intializers,这可以初始化由类内静态方法所需要的数据。
  • 它由不能被其他编译单元被添加到一个单元内明确括起来避免方法之间的名称冲突。


Answer 7:

由于Java,大多数程序员很容易地接受任何方法是一个类的成员。 我不作任何相当大的障碍,使方法更窄的概念,它使语言更容易。

然而,事实上,类推断对象和对象推断状态,所以类只包含静态方法的概念显得有些荒谬。



Answer 8:

我觉得你真的需要澄清你想创建非成员的静态方法来实现的。

举例来说,一些事情你可能想他们可以与处理扩展方法

(只包含静态方法的类的)另一种典型应用是在库中。 在这种情况下,存在在其中完全由静态方法的组件创建类危害小。 这让他们在一起,避免了命名冲突。 毕竟,有数学静态方法用于相同目的。

此外,你应该不必比较C ++的使用C#的对象模型。 C ++是主要(但不完全)与C,它不具有类系统都兼容 - 所以C ++必须支持这种编程成语出的C遗留的,不针对任何特定的设计势在必行。



Answer 9:

熊东西记:C ++比C#一个复杂得多的语言。 虽然他们可能会句法similiar,他们是非常不同的东西语义。 你不会认为这将是非常困难做出这样的改变,但我能看到这怎么可能。 ANTLR有一个叫做很好的维基页面是什么让一个语言问题难? 这是很好的这样的问题进行磋商。 在这种情况下:

上下文敏感的词法分析器? 你不能决定以匹配vocabulay符号,除非你知道你正在分析什么样的句子。

现在,而不是只担心在类中定义的功能,我们不必担心外界的类定义的功能。 从概念上讲,没有太大的区别。 但在词法方面和解析的代码,现在你不必说“如果一个函数是一个类之外,它属于这个无名类的额外的问题。但是,如果它是类里面,然后将属于此类。”

此外,如果编译器遇到这样的方法:

public void Foo()
{
    Bar();
}

......现在必须回答这个问题:“是酒吧位于这个类中或者是一个全球性的课吗?”

转发或外部引用? 即,多遍需要? 帕斯卡有一个“转发”参考处理文件内部程序引用,但通过的使用条款等其他文件中的程序引用...需要进行特殊处理。

这是造成问题的另一件事。 请记住,C#不需要前置声明。 编译器将完成一次走刀只是为了确定被命名为哪些类和这些类包含哪些功能。 现在你要担心找不到类函数的功能,可以是内部或类之外。 这是一个东西C ++解析器不必担心,因为它为了解析一切。

现在不要误会我的意思,它很可能在C#来完成,我可能会使用这样的功能。 但是否真的值得克服这些障碍时,你可以只是一个静态的方法前输入一个类名的所有的麻烦?



Answer 10:

如果你有鸭打字结合他们免费功能是非常有用的。 整个C ++ STL是基于它。 因此,我相信C#将推出免费的功能,当他们设法添加真正的仿制药。

像经济学,语言设计也即将心理。 如果您创建通过免费功能,在C#泛型真实的食欲和不能提供,那么你就杀了C#。 然后,所有的C#开发者将移动到C ++,并没有人愿意这样的事情发生,而不是C#社区肯定不是那些投资于C ++。



Answer 11:

虽然这是事实,你需要一个类(如静态类称为FreeFunctions )持有这样的功能,你可以自由地将using static FreeFunctions; 在需要从它的功能中的任何文件的顶部,而无需与垃圾代码FreeFunctions. 预选赛。 我不知道是否确实有这哪里是demonstrably不如不要求被包含在一个类中的函数定义的情况下。



Answer 12:

如果你想想看,在相反的观点是:“为什么不C ++支持扩展方法”,而答案就在于他们的设计目标之内。

C ++为您提供了命名空间,你可以任意对象,它会帮助你“推”以某种方式,对象上调用函数。

大部分的时间我用于在C命名空间功能++是创建一个接受对象的功能和做的,我不希望把一个类的成员函数中的功能。

在C#中,您可以创建为您做这项工作(大部分时间)的扩展方法。 对于还剩下些什么的情况下,你会错过这个功能。

就拿下面的代码:

template<typename T>
unsigned int findCount(vector<T>& vec, T data){
    unsigned int count = 0;
    for(auto val : vec)
        if(val == data) ++count;
    return count;
}

现在,如果我需要的功能在我的类中的一些目的,我可以将它添加到类的命名空间,并使用它,而“污染”我与该功能类。

在C#中,你可以实现与扩展方法相同的目标:

static class Extensions {
    public static uint FindCount<T>(this List<T> list, T data) {
        uint counts = 0;
        foreach (var item in list)
            if (item.Equals(data)) ++counts;
        return counts;
    }
}

且二者的工作这是很酷的方式相同。 许多人会争论C ++缺少扩展方法,许多人会争论C#缺少的命名空间功能。

我认为把它是因为它们与不同实现不同的语言,这些语言不是比较一些细节的最佳方式。

正如你在你的问题,引用C ++ / CLI没有“真正”的支持空间成员函数,因为它增加了一个无名类使用它们这是没有办法接近C ++实现,也许接近它的样子,但实际上不同。

最后,功能性的东西总是值得期待的,并不亚于我想在C#中的命名空间的成员函数是像我想用C扩展方法++。 这是不是反正很多。



文章来源: Why C# is not allowing non-member functions like C++