创建适用于System.Object的扩展方法的好习惯?

Chr*_*ian 9 .net c# extension-methods data-access

我想知道是否应该创建适用于对象级别的扩展方法,或者它们是否应该位于类层次结构中的较低点.我的意思是:

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
Run Code Online (Sandbox Code Playgroud)

我编写了这些方法,因为我必须处理很多数据库数据(来自OleDbDataReader),这些数据可以为null(不应该),因为底层数据库可能非常宽松,列可能为null.为了让我的生活更轻松,我想出了那些扩展方法.

我想知道的是这是好风格,可接受的风格还是坏风格.我有点担心它,因为它有点"污染"对象类.

提前谢谢你和最好的问候:)

基督教

PS我没有故意将其标记为"主观".

Pat*_*her 7

,这不是好的做法.您希望在尽可能低的点应用扩展方法.我相信(几乎)所有东西都有时间和地点,但扩展方法System.Object几乎永远不合适.您应该能够在继承堆栈中进一步应用扩展方法.否则它会混乱你的智能感知,并可能最终被其他开发人员错误地使用/依赖.

但是,用于处理Null值的数据对象的扩展方法是扩展方法的一个很好的用法.考虑将它们放在OleDbDataReader上.我有一个名为ValueOrDefault的通用扩展方法...好吧,我会告诉你:

<Extension()> _
Public Function ValueOrDefault(Of T)(ByVal r As DataRow, ByVal fieldName As String) As T
    If r.IsNull(fieldName) Then
        If GetType(T) Is GetType(String) Then
            Return CType(CType("", Object), T)
        Else
            Return Nothing
        End If
    Else
        Return CType(r.Item(fieldName), T)
    End If
End Function
Run Code Online (Sandbox Code Playgroud)

这是VB,但你得到了图片.这个吸盘节省了我很多时间,并且在读出数据流时真正能够获得干净的代码. 你是在正确的轨道上,但你的咒语感是正确的:你的扩展方法太高了.

将扩展方法放在一个单独的命名空间中总比没有好(这是命名空间的完全有效使用; Linq使用它),但你不应该这样做.要使这些方法适用于各种db对象,请将扩展方法应用于IDataRecord.


Mar*_*ann 6

在一般情况下,System.Object 的扩展方法污染可能非常烦人,但您可以将这些扩展方法放置在单独的命名空间中,以便开发人员必须主动选择使用这些方法。

如果将此与遵循单一职责原则的代码结合起来,则只需在相对较少的类中导入此命名空间。

在这种情况下,这样的扩展方法可能是可以接受的。


Ste*_*ven 5

框架设计指南建议你不要这样做。但是,这些准则特别适用于框架,因此,如果您发现它在您的业务应用程序中非常有用,请这样做。

但是请注意,在对象上添加这些扩展方法可能会使IntelliSense混乱,并可能使其他开发人员感到困惑。他们可能不希望看到这些方法。在这种情况下,只需使用老式的静态方法即可:-)


我个人发现,到处都是我的CPU(我的大脑)受过训练以寻找可能NullReferenceException的方法,而在各处都撒满了扩展方法,这是一件令人不安的事情。因为扩展方法看起来像实例方法,所以我的大脑在读取此类代码时经常会受到源代码解析器PossibleUseOfNullObject中断。在那种情况下,我必须分析a是否可以实际发生。这使阅读代码变得更加困难,因为我经常被打扰。NullReferenceException

因此,我对使用扩展方法非常保守。但这并不意味着我不认为它们有用。一定不行!我什至编写了一个用于前提条件验证的库,该库广泛使用扩展方法。我甚至最初定义的扩展方法System.Object,当我开始写这个库。但是,由于这是一个可重用的库,并且被VB开发人员使用,因此我决定在上删除这些扩展方法System.Object


Dan*_*elo 5

摘自"框架设计指南"一书

除非绝对必要,否则请避免在System.Object上定义扩展方法.这样做时,请注意VB用户将无法使用如此定义的扩展方法,因此,他们将无法利用扩展方法带来的可用性/语法优势.

这是因为,在VB中,将变量声明为对象会强制对其进行所有方法调用后期绑定 - 而对扩展方法的绑定则是编译时确定的(早期绑定).例如:

public static class SomeExtensions{
     static void Foo(this object o){…} } … Object o = … o.Foo(); 
Run Code Online (Sandbox Code Playgroud)

在此示例中,对Foo的调用将在VB中失败.相反,VB语法应该只是:SomeExtensions.Foo(o)
请注意,该指南适用于存在相同绑定行为的其他语言,或者不支持扩展方法的其他语言