这是静态方法的正确使用吗

本文关键字:静态方法 | 更新日期: 2023-09-27 18:22:44

关于静态方法的使用,我读到了很多相互矛盾的意见,这让我头疼。考虑以下内容:

在我的大多数CRUD应用程序中,我使用SqlDataHandler类来处理与一个类(或者在某些情况下是一组类)的数据库的交互。见下文:

public abstract SqlDataHandler
{
    #region Properties
    protected static string ConnectionString { get; set; }
    #endregion
    #region Methods
    protected static DataTable GetDataTable(SqlCommand GetTableCommand)
    {
        ...
    }
    #endregion  
}
public AccountSqlDataHandler : SqlDataHandler
{
    #region Methods
    public static DataTable GetAccountHistory()
    {
        SqlCommand getAccountHistoryCommand;
        ...
        return AccountSqlDataHandler.GetDataTable(getAccountHistoryCommand);
    }
    #endregion
    #region Ctors
    static AccountSqlDataHandler()
    {
        AccountSqlDataHandler.ConnectionString = "Connection string for account database";
    }
    #endregion
}

public Account
{
    #region Properties
    public List<HistoryItem> AccountHistory
    {
        get
        {
            List<HistoryItem> accountHistory;
            accountHistory =         
                this.getItemsFromDataTable(AccountSqlDataHandler.GetAccountHistory());
        return accountHistory;
        }
    }
    #endregion
}

在我看来,如果我使用成员方法,那么每次都必须创建一个AccountSqlDataHandler实例,或者在Account类中创建一个AccountSqlDataHandler成员。我认为这样做没有任何好处,但从我所读到的内容来看,这是一个好处。在我盲目地改变我的方法之前,我想了解它是什么。

这是静态方法的正确使用吗

一个好的经验法则是,如果方法不依赖于特定实例,则使用静态方法。即

public static int Add (x, y)
{
    return x + y;
}

如果您确实依赖于实例,则应该使用实例方法。

public int Add(x)
{  
    return this.y + x;
}

现在您的具体问题是,也许您连接到多个数据库,或者您有多个连接字符串。

如果你这样做了,那么实例化sql数据处理程序是完全合理的。但如果你不这样做,就没有太多的需要。

没有。事实上,当您添加并使用第二个处理程序时,会有一个很好的bug。

试试这个代码(希望你能注意到与ConnectionString属性的相似之处):

internal class Program
{
    private static void Main(string[] args)
    {
        var bravo = new Bravo();
        var charlie = new Charlie();
        Console.WriteLine(bravo.GetValue());
        Console.WriteLine(charlie.GetValue());
        Bravo.EchoValue();
        Charlie.EchoValue();
    }
}
public abstract class Alpha
{
    protected static string Value { get; set; }
    public abstract string GetValue();
}
public class Bravo : Alpha
{
    static Bravo()
    {
        Value = "bravo";
    }
    public override string GetValue()
    {
        return Value;
    }
    public static void EchoValue()
    {
        Console.WriteLine(Value);
    }
}
public class Charlie : Alpha
{
    static Charlie()
    {
        Value = "charlie";
    }
    public override string GetValue()
    {
        return Value;
    }
    public static void EchoValue()
    {
        Console.WriteLine(Value);
    }
}

输出:

查理查理查理查理按任意键继续。

ConnectionString是有效的共享状态,在静态构造函数中修改它意味着最后一个静态构造函数调用将为整个应用程序设置状态(直到有东西将其设置为它想要的状态,但这个必须是规则,然后静态构造函数就没有意义了)。这将不可避免地导致为什么我的账户查询会进入订单数据库问题(因为开发人员在每次使用之前都没有明确设置连接字符串),并扼杀了该应用程序在多数据库上下文中工作的任何机会。

通常情况下,当行为在逻辑上属于classtype时,static应该是某种东西,而不是它的实例,当数据在所有实例之间共享时,它应该是静态数据。在您的情况下,看起来您希望每个数据库都有一个Singleton。看看这个图案。很多次我看到singleton被实现为静态类/方法,这是不正确的。

NET中的另一件事是,有一个通用准则,即静态方法是(应该是)线程安全的,而实例方法不是。在实现静态方法时,您必须注意这一准则。