创建适用于 System.Object 的扩展方法的良好做法?
我想知道是否应该创建适用于对象级别的扩展方法,或者它们是否应该位于类层次结构中的较低位置。我的意思是这样的:
public static string SafeToString(this Object o) {
if (o == null || o is System.DBNull)
return "";
else {
if (o is string)
return (string)o;
else
return "";
}
}
public static int SafeToInt(this Object o) {
if (o == null || o is System.DBNull)
return 0;
else {
if (o.IsNumeric())
return Convert.ToInt32(o);
else
return 0;
}
}
//same for double.. etc
我编写了这些方法,因为我必须处理大量可以为空的数据库数据(来自 OleDbDataReader)(但不应该),因为不幸的是底层数据库非常 自由,列可能为空。为了让我的生活更轻松一些,我想出了这些扩展方法。
我想知道这是好的风格、可接受的风格还是坏的风格。我有点担心它,因为它有点“污染”对象类。
预先感谢您&最好的问候:)
Christian
P.S.我并不是故意将其标记为“主观”。
I'm wondering whether I should create extension methods that apply on the object level or whether they should be located at a lower point in the class hierarchy. What I mean is something along the lines of:
public static string SafeToString(this Object o) {
if (o == null || o is System.DBNull)
return "";
else {
if (o is string)
return (string)o;
else
return "";
}
}
public static int SafeToInt(this Object o) {
if (o == null || o is System.DBNull)
return 0;
else {
if (o.IsNumeric())
return Convert.ToInt32(o);
else
return 0;
}
}
//same for double.. etc
I wrote those methods since I have to deal a lot with database data (From the OleDbDataReader) that can be null (shouldn't, though) since the underlying database is unfortunately very liberal with columns that may be null. And to make my life a little easier, I came up with those extension methods.
What I'd like to know is whether this is good style, acceptable style or bad style. I kinda have my worries about it since it kinda "pollutes" the Object-class.
Thank you in advance & Best Regards :)
Christian
P.S. I didn't tag it as "subjective" intentionally.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不,这不是一个好的做法。您希望在尽可能低的点应用扩展方法。我相信(几乎)所有事情都有一个时间和地点,但扩展方法 System.Object 几乎永远不会合适。您应该能够在继承堆栈的更深处应用此类扩展方法。否则,它会使您的智能感知变得混乱,并可能最终被其他开发人员错误地使用/依赖。
然而,用于处理 Null 值的数据对象的扩展方法是扩展方法的非常好的用途。考虑将它们放在您的OleDbDataReader上。我有一个名为 ValueOrDefault 的通用扩展方法。 。 。好吧,我就给你演示一下:
那是 VB,但你明白了。这个傻瓜节省了我大量的时间,并且在读取数据行时确实可以生成干净的代码。 你的方向是正确的,但你的咒语感是正确的:你的扩展方法太高了。
将扩展方法放入单独的命名空间中总比没有好(这是命名空间的完全有效的使用;Linq 使用此),但您不必这样做。要使这些方法适用于各种数据库对象,请将扩展方法应用于IDataRecord。
No, that is not good practice. You want to apply extension methods at the lowest possible point. I believe there a time and a place for (almost) everything, but extension methods System.Object would almost never be appropriate. You should be able to apply extension methods such as this much further down the inheritance stack. Otherwise it will clutter your intellisense and probably end up being used/depended-upon incorrectly by other developers.
However, extension methods for data objects for dealing with Null values is a very good use of extension methods. Consider putting them right on you OleDbDataReader. I have a generic extension method called ValueOrDefault that . . . well, I'll just show it to you:
That's VB, but you get the picture. This sucker saves me a ton of time and really makes for clean code when reading out of a datarow. You are on the right track, but your sense of spell is correct: you have the extension methods too high.
Putting the extension methods into a separate namespace is better than nothing (this is a perfectly valid use of namespaces; Linq uses this), but you shouldn't have to. To make these methods apply to various db objects, apply the extension methods to IDataRecord.
在一般情况下,System.Object 的扩展方法污染可能非常烦人,但您可以将这些扩展方法放置在单独的命名空间中,以便开发人员必须主动选择使用这些方法。
如果将此与遵循单一职责原则的代码结合起来,则只需在相对较少的类中导入此命名空间。
在这种情况下,这样的扩展方法可能是可以接受的。
Extension method pollution of System.Object can be quite annoying in the general case, but you can place these extension methods in a separate namespace so that developers must actively opt in to use those methods.
If you couple this with code that follows the Single Responsibility Principle, you should only have to import this namespace in relatively few classes.
Under such circumstances, such extension methods may be acceptable.
摘自《框架设计指南》一书
An excerpt from the book "Framework design guidelines"
框架设计指南建议您不要这样做。但是,这些指南特别适用于框架,因此如果您发现它在您的(行业)业务应用程序中非常有用,请这样做。
但请注意,在对象上添加这些扩展方法可能会使 IntelliSense 混乱,并可能使其他开发人员感到困惑。他们可能不希望看到这些方法。在这种情况下,只需使用旧式静态方法:-)
One thing I personally find troubling about sprinkling extension methods everywhere it that my CPU (my brain) is trained to find possible `NullReferenceException`s. Because an extension method looks like an instance method, my brain often receives a `PossibleUseOfNullObject` interrupt by the *source code parser* when reading such code. In that case I have to analyze whether a `NullReferenceException` can actually occur or not. This makes reading through the code much harder, because I'm interrupted more often.
因此,我对使用扩展方法非常保守。但这并不意味着我认为它们没有用。天啊不!我什至编写了广泛使用扩展方法的用于前提条件验证的库。我什至在
System.Object
最初定义的扩展方法 > 当我开始编写那个库时。然而,因为这是一个可重用的库并且由 VB 开发人员使用,所以我决定删除System.Object
上的这些扩展方法。The Framework Design Guidelines advice you not to do this. However, these guidelines are especially for frameworks, so if you find it very useful in your (line of) business application, please do so.
But please be aware that adding these extension methods on object might clutter IntelliSense and might confuse other developers. They might not expect to see those methods. In this case, just use old fashion static methods :-)
One thing I personally find troubling about sprinkling extension methods everywhere it that my CPU (my brain) is trained to find possible `NullReferenceException`s. Because an extension method looks like an instance method, my brain often receives a `PossibleUseOfNullObject` interrupt by the *source code parser* when reading such code. In that case I have to analyze whether a `NullReferenceException` can actually occur or not. This makes reading through the code much harder, because I'm interrupted more often.
For this reason I’m very conservative about using extension methods. But this doesn’t mean I don’t think they’re useful. Hell no! I've even written a library for precondition validation that uses extension methods extensively. I even initially defined extension methods on
System.Object
when I started writing that library. However, because this is a reusable library and is used by VB developers I decided to remove these extension methods onSystem.Object
.也许考虑将扩展方法添加到 IDataRecord 接口? (您的 OleDbDataReader 实现)
Perhaps consider adding the extension methods to the IDataRecord interface? (which your OleDbDataReader implements)
我知道这不是最佳实践,但对于我的项目,我喜欢包含这个用于转换数据类型的扩展,我发现它比 Convert 类容易得多。
它会显示在每个对象中,但我通常只使用这个而不是有一个扩展列表..
像这样工作...
I know its not best practice, but for my projects I like to include this extension for converting data types, i find it much easier than the Convert class..
It'll show up in every object but i usually just use this one instead of having a list of extensions..
Works like this...
除了已经提到的原因之外,还应该记住,VB 中不支持
System.Object
上的扩展方法(只要变量静态类型为System.Object< /code> 并且如果变量不是静态类型为
Object
你应该更好地扩展另一个更具体的类型)。造成此限制的原因是向后兼容性。请参阅此问题 了解更多详情。
In addition to the reasons already mentioned, it should be borne in mind that extension methods on
System.Object
are not supported in VB (as long as the variable is statically typed asSystem.Object
and if the variable is not statically typed asObject
you should better extend another more specific type).The reason for this limitation is backward compatibility. See this question for further details.