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

时间:2013-07-16 17:26:09

标签: c# oop

我已经阅读了很多关于使用静态方法的相互矛盾的意见。请考虑以下事项:

在我的大多数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成员。我认为这样做没有任何好处,但从我正在阅读的内容中看,这是一个优势。在盲目改变我的方法之前,我想了解它是什么。

3 个答案:

答案 0 :(得分:3)

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

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

如果依赖实例,则应使用实例方法。

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

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

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

答案 1 :(得分:2)

不。事实上,当你添加和使用第二个处理程序时,会有一个很好的错误。

尝试使用此代码(希望您会注意到与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);
    }
}

输出:

charlie
charlie
charlie
charlie
Press any key to continue . . .

ConnectionString是有效的共享状态,在静态构造函数中修改它意味着最后一个静态构造函数调用将设置整个应用程序的状态(直到某些东西将它设置为它想要的状态但是这个必须成为规则然后静态构造函数是毫无意义的。这将不可避免地导致为什么我的帐户查询命中数据库?问题(因为开发人员没有在每次使用之前显式设置连接字符串)以及杀死此应用程序的任何机会在多数据库环境中工作。

答案 2 :(得分:1)

一般来说,static应该是这样的行为,当该行为在所有实例之间共享时,逻辑上属于classtype而不是其实例和静态数据。 在您的情况下,您似乎希望每个数据库都有Singleton。看看那种模式。很多时候我看到单例被实现为静态类/方法,这是不正确的。

.NET中的另一个问题是,一般的准则是静态方法(应该)是线程安全的,但实例方法不是。在实现静态方法时,您必须遵守本指南。