所以,我真的很喜欢使用扩展方法..也许有点太多了。所以,我会问我最近的享受,以确保我不会走得太远。
场景是我们传入了一个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);
如果不使用扩展方法,这是不可能的,在我看来可能会产生误导。但是,它只是如此简洁和干净!所以你怎么看?这是可接受的事情,还是让其他程序员感到困惑?
另外,我确信会有其他情况我会做这样的事情并检查this
是否为null,但这是我现在最好的例子。
注意:我并不是真的特别询问这个Guid?
业务。我正在询问有关实施的整体模式的更多信息(使用this
可以null
的扩展方法)
答案 0 :(得分: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)
答案 1 :(得分:3)
我个人认为会有更多的开发人员更好更快地理解(所以最终意味着代码更清晰):
if (!guid.HasValue || guid.Value == Guid.Empty)
{
return other;
}
而不是:
((Guid?)null).OrIfEmpty(other);
所以这取决于你是为自己编码还是你写的东西可以得到其他人的支持。我个人认为增值不值得“怪异”:)
答案 2 :(得分: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
不为空,您不能使用扩展方法进行该假设。
答案 3 :(得分:1)
我没有看到任何问题。回想一下
string.IsNullOrEmptyOrWhitespace
来自stdlib。
一般来说,这取决于你对那个空案例做什么。如果以正常方式使用该函数,并且该函数在该特殊情况下表现正常 - 一切正常。但是,如果你的函数进入调试模式并开始重新配置系统,那么,你已经越过了最小的原则 - 那就是不好
- 注意:正如@JeppeStigNielsen准确指出的那样,INOEOW 不是当前版本.Net中的扩展方法。我确信我有几次作为扩展方法,但很可能它是在一些CTP版本或者它可能是旧版本的.Net的自定义插件,它根本不存在。对困惑感到抱歉!尽管如此,“这都是关于正确命名的”stil持有! :)
答案 4 :(得分: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