当谈到扩展方法时,类名似乎什么也不做,但提供了一个名称空间的分组。只要我包含命名空间,我就会在命名空间中获得所有扩展方法。所以我的问题归结为:我可以从静态类中的扩展方法获得一些值吗?
我意识到将它们放入静态类是编译器的要求,但从组织的角度来看,允许在没有类的名称空间中定义扩展方法是合法的是合理的。围绕着他们。用另一种方式重新解释上述问题:作为开发人员,在某种情况下是否有任何实际的好处或帮助,因为将扩展方法附加到类而不是附加到命名空间?
我基本上只是想获得一些直觉,确认或洞察力 - 我怀疑这可能是最容易实现扩展方法的方式,并且不值得花时间让扩展方法自己存在在名字空间。
答案 0 :(得分:3)
也许你会在Eric Lippert的博客文章Why Doesn't C# Implement "Top Level" Methods?中找到一个满意的答案(反过来由SO问题Why C# is not allowing non-member functions like C++提示),从那里(我的强调):
我被问到“为什么C#不实现功能X?”每时每刻。该 答案总是一样的:因为没有人设计,指定, 实施,测试,记录和发送该功能。全部六个 这些东西是使功能发生所必需的。所有这些都是成本 大量的时间,精力和金钱。功能并不便宜,我们 我们非常努力地确保我们只提供这些功能 这给我们的用户带来了最好的好处 限制时间,精力和预算。
据我所知,这样的一般答案可能并未解决这个问题 具体问题。
在这种特殊情况下,明显的用户利益在过去并非如此 大到足以证明语言的复杂性 随之而来。通过限制不同语言实体在每个实体中的嵌套方式 其他我们(1)将法律程序限制在一个共同的,容易的 理解风格,(2)可以定义“标识符” 查找“易于理解,可指定,可实施的规则, 可测试和可记录的。
通过将方法主体限制为始终位于结构或类中,我们可以更容易地推断出不合格的含义 调用上下文中使用的标识符;这样的事总是一个 当前类型(或基本类型)的可调用成员。
答案 1 :(得分:1)
对我来说,将它们放入类中就是将类中的相关函数分组。您可能在同一名称空间中有许多扩展方法。如果我想为DirectoryInfo和FileInfo类编写一些扩展方法,我将在名为DirectoryInfoExtensions和FileInfoExtensions的IO命名空间中创建两个类。
您仍然可以像调用任何其他静态方法一样调用扩展方法。我不知道编译器是如何工作的,但是如果编译为.net 2的输出程序集仍然可以被遗留的.net框架使用。它还意味着现有的反射库可以工作并用于运行扩展方法而无需任何更改。我不再是编译器专家,但我认为扩展方法上下文中的“this”关键字是允许我们使用这些方法的语法糖,就好像它们属于对象一样。
答案 2 :(得分:1)
.NET Framework要求每个方法都存在于程序集中的类中。语言可以允许在没有显式指定的封闭类的情况下声明方法或字段,将程序集Fnord
中的所有此类方法放入名为Fnord_TopLevelDefault
的类中,然后搜索Fnord_TopLevelDefault
类的Foo
类执行方法查找时的所有程序集;但是,必须扩展CLS规范才能使此功能顺利地用于混合语言项目。与扩展方法一样,如果CLS不承认,这种行为可能符合CLS,因为使用不使用此类功能的语言中的代码可以在程序集中使用“自由浮动”方法Fnord
{ {1}}拼写Fnord_TopLevelDefault.Foo
,但这有点难看。
一个更有趣的问题是允许从任意类调用扩展方法Foo
而不要求对该类进行明确可见的引用的程度比允许非扩展静态方法更少邪恶同样被援引。我不认为Math.Sqrt(x)
比Sqrt
更具可读性;即使一个人不想在任何地方导入Math
,至少在本地也能这样做可以在某些情况下大大提高代码的可读性。
答案 3 :(得分:0)
他们可以在内部引用其他静态类成员。
您不仅应考虑消费者方面,还应考虑代码维护方面。
即使intellisense没有区分所有者类,但仍然可以通过工具提示以及您添加到IDE中的任何生产力工具来获取信息。这可以很容易地用于为方法提供一些上下文,否则将是一个扁平(有时很长)的列表。
消费者明智,底线,我认为这不重要。