“null this”是否可以使用扩展方法?

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

情景是我们有一个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”不会抛出exception。 例如,这将工作:

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

如果不使用扩展方法,这是不可能的,在我看来可能会产生误导。 然而,它只是如此简洁和干净! 所以你怎么看? 这是可以接受的事情,还是对其他程序员来说太混乱了?

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

注意:我真的不是在问这个Guid? 特别是生意。 我要求更多关于实现的整体模式(有一个扩展方法,其中可以为null

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

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

在我看来,可能会产生误导

我同意,因为它看起来像是null实例上调用实例方法。 这可能会更糟:

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

乍一看,这看起来像一个明显的NullReferenceException等待发生,但它编译并按设计工作。

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

 internal static Guid OrIfNullOrEmpty(this Guid? guid, Guid other) 

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

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

而不是:

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

所以这取决于你是为自己编码还是你所写的东西可以得到其他人的支持。 就个人而言,我认为增值不值得“怪异”:)

通常,扩展方法应检查空值。 毕竟,扩展方法只不过是一个静态方法,添加了一些语法糖,因此编译器可以像处理实例方法一样对待它。

例如,如果你有这个:

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

然后你可以用两种不同的方式调用它:

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

而使用普通实例方法,您可以假设this不是null,您不能使用扩展方法进行该假设。

我没有看到任何问题。 回想一下

string.IsNullOrEmptyOrWhitespace

来自stdlib。

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

– 注意:正如@JeppeStigNielsen准确指出的那样,INOEOW 不是当前版本的.Net中的扩展方法。 我确信我有几次作为扩展方法,但很可能它是在一些CTP版本或者它可能是旧版本的.Net的自定义插件,它根本不存在。 对困惑感到抱歉! 尽管如此,“这都是关于正确命名的”stil持有! 🙂

我觉得这没关系。 请注意,使用Nullable的示例并不是那么糟糕,因为Nullable类型的所谓nullNullable的实际值和现有值,而不是“无”。

这就是为什么你也可以在这种“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