9

所以,我真的很喜欢使用扩展方法……也许有点太多了。所以,我要问一下我最近的享受,以确保我不会走得太远。

场景是我们有一个Guid?传入的变量。如果变量为 null 或Guid.Empty,那么我们想要使用不同的 Guid。所以,我写了一个扩展方法让它读起来像英语:

    internal static Guid OrIfEmpty(this Guid? guid, Guid other)
    {
        if (!guid.HasValue || guid.Value == Guid.Empty)
        {
            return other;
        }
        return guid.Value;
    }

这自动意味着“null this”不会引发异常。例如,这将起作用:

((Guid?)null).OrIfEmpty(other);

如果不使用扩展方法,这是不可能的,而且在我看来可能会产生误导。但是,它是如此简洁和干净!所以你怎么看?这是一件可以接受的事情吗,还是会让其他程序员感到困惑?

此外,我确信在其他情况下我会做这样的事情并检查thisnull,但这是我现在拥有的最好的例子。

注意:我并不是真的Guid?特别询问这项业务。我在询问更多关于实现的整体模式(有一个this可以的扩展方法null

4

5 回答 5

5

如果不使用扩展方法,这是不可能的

当然可以,只是 make 是一个常规的静态方法调用(所有扩展方法都是):

在我看来可能会产生误导

我同意,因为看起来您正在对实例调用实例方法null。这可能会更糟:

string s = null;
string n = s.OrIfEmpty("empty");

乍一看,这似乎是一个明显的NullReferenceException等待发生,但它按设计编译和工作。

由于您的问题实际上只是征求意见,因此没有一个正确答案,但我当然会谨慎并记录扩展方法以表明this参数可能是null. 或者(正如@quezalcoatl 暗示的那样)重命名它以更明确地支持null值:

internal static Guid OrIfNullOrEmpty(this Guid? guid, Guid other)
于 2013-01-28T16:06:52.547 回答
3

我个人认为会有更多的开发人员更好更快地理解(所以最终意味着代码更干净):

if (!guid.HasValue || guid.Value == Guid.Empty)
{
    return other;
}

而不是:

((Guid?)null).OrIfEmpty(other);

因此,这取决于您是为自己编写代码,还是您编写的内容可以得到其他人的支持。就我个人而言,我认为增加的价值不值得“怪异”:)

于 2013-01-28T16:02:03.220 回答
1

通常,扩展方法应该检查空值。毕竟,扩展方法只不过是添加了一些语法糖的静态方法,以便编译器可以将其视为实例方法。

例如,如果你有这个:

public static class MyExtensions
{
    public static IEnumerable<TSource> Frob<TSource>(this TSource source)
    {
        // do stuff here
    }
}

然后,您可以通过两种不同的方式调用它:

var foo = new List<int>();
var bar = foo.Frob();  // called like an instance method
var barby = MyExtensions.Frob(foo); // called like a static method

虽然使用普通实例方法,您可以假设它this不为空,但您不能使用扩展方法做出该假设。

于 2013-01-28T16:04:54.040 回答
1

我认为这没有任何问题。只记得

string.IsNullOrEmptyOrWhitespace

来自标准库。

一般来说,这取决于将如何处理该空案例。如果您以正常方式使用该函数,并且该函数在该特殊情况下正常运行 - 一切正常。但是,如果您的函数进入调试模式并开始重新配置系统,那么您已经越过了最小惊讶原则,这并不好

-- 注意:正如@JeppeStigNielsen 准确指出的那样,INOEOW不是当前版本的.Net 中的扩展方法。我确信我曾多次使用它作为扩展方法,但很可能它是在某些 CTP 版本上,或者它可能是旧版本 .Net 的自定义插件,它根本不存在。对困惑感到抱歉!尽管如此,“这都是关于正确命名的”仍然成立!:)

于 2013-01-28T16:06:02.367 回答
0

我认为这没关系。请注意,带有的示例并Nullable<Guid>没有那么糟糕,因为所谓null的类型Nullable<Guid>是 的真实和现有值Nullable<Guid>,而不是“无”。

这就是为什么你也可以在这种“null”上使用实例方法,如

Guid? g = null;
g.GetValueOrDefault();  // OK; real instance method

将其与引用类型一起使用更加“奇怪”:

internal static string OrIfEmpty(this string str, string other)
{
  return string.IsNullOrEmpty(str) ? other : str;
}

因为那样你就可以在“真正的”空值上调用它:

string s = null;
s.OrIfEmpty("unspecified");  // OK; s is a true null reference
于 2013-01-28T16:08:48.697 回答