我最近一直在使用扩展方法,并且发现了很多用途。我唯一的问题是记住它们的位置以及使用哪些命名空间来获取扩展方法。
但是,我最近考虑过在System命名空间,System.Collections命名空间或其他一些有意义的系统命名空间中编写扩展方法。例如,我已经实现了以下内容。
namespace System
{
/// <summary>Various array extensions</summary>
public static class ArrayExtensions
{
/// <summary>Converts the array to a hex string</summary>
/// <param name="value">The value.</param>
/// <returns>The array as a hex string</returns>
public static string ToHexString(this byte[] value)
{
var hex = new StringBuilder(value.Length * 2);
foreach (byte b in value)
{
hex.AppendFormat("{0:X2}", b);
}
return hex.ToString();
}
}
}
这是正确的做法吗?
答案 0 :(得分:22)
来自框架设计指南(第2版):
不要将扩展方法放在与扩展类型相同的命名空间中,除非它是用于向接口添加方法或用于依赖关系管理。
虽然这没有明确涵盖您的场景,但您通常应该避免扩展Framework命名空间(或您无法控制的任何命名空间),而是选择将这些扩展放在它们自己的命名空间中。如果您强烈想要对分组进行“分组”(以便集合扩展在一起等),那么您可以引入一个子名称空间。在您的方案中,对集合的扩展将位于System.Collection.Extensions
命名空间或Company.Collections
甚至Company.Collections.Extension
命名空间中。
为了使用扩展方法,必须导入包含Sponsor类(定义扩展方法的类)的命名空间。如果将扩展方法添加到其中一个标准.NET Framework命名空间,它们将始终(并且隐式)可用。
答案 1 :(得分:14)
您应该避免扩充您没有主控制的名称空间,因为将来的更改可能会破坏您的代码(例如,通过引入重复项)。
我倾向于使用不同的根命名空间来模仿标准命名空间,该命名空间将所有子命名空间标识为属于我的工作。根命名空间可以是您的名称,组织的名称或标识该命名空间内容的其他名称。
例如,如果您想扩展System.Collections
,则可以使用NickR.Collections
或NickR.System.Collections
。
答案 2 :(得分:4)
命名空间对扩展方法的唯一影响是可见性和可发现性 - 因此它取决于您是否希望扩展方法始终显示在该类型上。框架设计指南主要用于公共API,因此,虽然遵循它们通常是一个好主意,但在有意义的情况下,内部API的规则将被打破。
例如,我们在整个代码库中对TimeSpan
个对象进行了大量工作,并且没有方法在框架中对这些对象进行乘法或除法,因此我们添加了MultiplyBy
和DivideBy
扩展方法,以及将它们放在System
命名空间中,因为我们希望它们在TimeSpan
被使用的任何地方都可访问和发现。
另一方面,我们也做了很多反思工作,对Type
个对象进行操作,并且有很多扩展方法在特定区域非常有用,但一般情况下并不常用,因此它们存在于OurCompany.Reflection
命名空间,因此必须专门导入它们。
因此,对于内部API,决策归结为“我希望这种方法在我们的代码库中可用的类型的任何地方都可用吗?”。如果答案是肯定的,那么将它放在同一名称空间中,否则将其放在其他地方。
答案 3 :(得分:3)
不确定是否错误(或者说是对的),但为什么不拥有自己的'Extensions'命名空间?然后将所有扩展方法放在该命名空间中并保持一致。
我认为真正的问题不在于放置它们或者命名它(系统或任何其他命名空间),而是要保持一致并始终使用相同的方法来避免您的问题(忘记它们的位置)。 / p>
答案 4 :(得分:0)
我将扩展方法放在命名空间中,具体取决于我希望它们具有的可见性。这样他们就更容易被发现,而且我通常会获得更少的命名空间导入。