23

有点学术问题,但我试图更深入地理解框架设计。

所以我们有String.IsNullOrEmpty(MyString)

我们可以编写一个扩展方法来启用myString.IsNullOrEmpty(),尽管这可能不是最好的主意。请参阅:使用 IsNullOrEmpty 扩展 String 类是否令人困惑?.

所以我的问题是,为什么 MS 不将此功能编写为 .Net 框架的一部分?是否有一些性能考虑?更一般地说,为什么任何被视为有价值的方法或属性可以构建为可通过 String 对象访问,但不能作为字符串类型的任何对象的成员使用?

4

3 回答 3

35

静态方法String.IsNullOrEmpty是在 .NET Framework 2.0 版中引入的。扩展方法与 LINQ 一起在 .NET Framework 3.5 版中引入。因此微软在引入IsNullOrEmpty.

当然,IsNullOrEmpty不能是 的实例方法String,因为您不能在引用上调用方法是null。但是,您可以在此类引用上调用扩展方法,因为扩展方法语法只是静态方法调用的语法糖。


让我们假设这IsNullOrEmpty是一个扩展方法。然后你可以这样称呼它:

string s = null;
bool result = s.IsNullOrEmpty();

在评论中,有人假装这个调用会抛出一个NullReferenceException. 扩展方法将像这样声明:

public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string s)
    {
        return s == null || s.Length == 0;
    }
}

...并像这样使用...

 string s = null;
 bool result = s.IsNullOrEmpty();

...这只是...的语法糖

 string s = null;
 bool result = StringExtensions.IsNullOrEmpty(s);

...因此,不会抛出异常。这样做是否是一个好主意是另一个问题(请参阅下面的usr提供的答案)。

于 2013-01-07T13:15:10.187 回答
27

通常认为在引用上调用扩展方法时不会失败是一种不好的做法null。这是因为仅通过阅读代码,您无法判断正在调用扩展方法。您的直觉是看到呼叫((string)null).IsNullOrEmpty()失败。

显然,这种方法不可能作为实例方法。所以我们在这里违反直觉。

也就是说,我已经在我的所有重要项目中准确地定义了这个扩展,它在很多情况下都非常有用。我愿意接受这种小小的杂质和不直观。

框架作者显然不同意。我还认为这种方法不应该进入 .NET Framework,因为它有点“高级”并且阻碍了可学习性。初学者可能会问“嗯?有时我可以安全地调用空引用上的方法,有时我不能?如何判断何时?”。

于 2013-01-07T13:10:24.393 回答
6

因为如果您可以IsNullOrEmpty()在空字符串上使用,那么您可能希望将该方法重命名为IsEmpty().

撇开玩笑不谈,这是该方法的实现方式:

public static bool IsNullOrEmpty(string value)
{
  if (value != null)
    return value.Length == 0;
  else
    return true;
}

很明显,在字符串实例的情况下,条件总是为真。

另外,一个小细节。例如,string.Concat这是一个静态方法。例如,想知道为什么没有相对实例方法可能是合理的;通过查看它的实现,我相信他们想让这些方法尽可能地防故障。将参数传递给方法时,如果引用为空,则将它们替换为空字符串,而不是引发异常。当您事先不知道您的字符串是否实际包含值或为空时,这可能很有用,而且我猜框架的开发人员决定通过处理空字符串来提高代码的可读性会更好作为空的,并为最终用户节省了额外的检查。当然,如果string.Concat是一个实例方法(或者至少有一个替代方法),用户仍然可以传递空参数,但是正在操作的实例不一定是空的。

于 2013-01-07T13:06:57.803 回答