5

我对 C# 语言比较陌生,但是在 Google 搜索和 Stack Overflow 的帮助下,我已经完成了许多应用程序,其中包括使用 Office、系统服务、进程、WMI、SQL、Linq 和 Active Directory。 ..

尽管在使这些应用程序正常运行方面取得了成功,但我仍然不确定 C# 语言中的许多事情,例如良好的代码实践和使用许多关键字等。

C#类;我知道我可以用它们做什么,我知道构造函数和析构函数、实例化和属性,但我不确定什么时候应该使用它们。到目前为止,我已经在不同方法中的 Form1.cs 文件中编写了所有代码。这些方法使用完全不同的 API 做一系列不同的事情。这显然意味着尝试维护该代码可能会变得相当困难,而且我发现在我的 Form1.cs中找到任何东西越来越令人沮丧。

我对你们的问题是我应该将我的代码分成不同的类吗?我试图将与 SqlConnection 和 SqlCommands 相关的内容拆分到一个单独的类中,但没有在我的 Form1.cs 中多次实例化同一个类,我看不出这更容易或有任何好处。

我一直在尝试拼凑一个新的应用程序,但这次将功能保留在它自己的类中,我希望有人可以告诉我我很愚蠢并且做错了,或者至少给我一些指导。

这个应用程序最终将从 App.Config 加载我的连接字符串,连接到 SQL 数据库并使用数据库中的多个表填充 DataSet。这绝不是功能性的,因为我无法理解整个 Classes 问题。

partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    string myConnectionString;

    private void Form1_Load(object sender, System.EventArgs e)
    {
        AppConfig cfg = new AppConfig();
        if (cfg.loadConfig())
        {
            myConnectionString = cfg.myConnectionString();
        }
        
        if (!String.IsNullOrEmpty(myConnectionString))
        {
            SQLConn SQL = new SQLConn();
            if (SQL.createConnection(myConnectionString))
            {
                MessageBox.Show("Connected!");
            }
        }
    }
}

class myDataSet
{
    DataSet DataSet()
    {
        DataSet ds = new DataSet();

        SQLConn sql = new SQLConn();
        
        return ds;
    }

    public void fillData()
    {
        try
        {
            SqlCommand sqlCmd = new SqlCommand("SELECT * FROM hardware");                
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

class SQLConn : IDisposable
{
    SqlConnection sqlConn;
    public bool createConnection(string myConnectionString)
    {
        sqlConn = new SqlConnection();
        sqlConn.ConnectionString = myConnectionString;
        try
        {
            sqlConn.Open();
            return true;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        return false;
    }

    public void Dispose()
    {
        if (sqlConn.State == ConnectionState.Open)
        {
            sqlConn.Close();
            sqlConn.Dispose();
        }
    }
}

class AppConfig
{
    Configuration cfg;

    public bool loadConfig()
    {
        try
        {
            cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (!File.Exists(cfg.FilePath))
            {
                MessageBox.Show("No configuration file");
            }
            return true;
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        return false;
    }

    public string myConnectionString()
    {
        string connectionString = ConfigurationManager.ConnectionStrings["IT_ProjectConnectionString"].ConnectionString;
        return connectionString;
    }
}
4

3 回答 3

8

OOP 背后的原则或多或少说,您应该尽可能多地拆分内容,以便将相关的内容组合在自己的类中,就像您示例中的 SQL 内容一样。另一个经常使用的例子是汽车——如果你需要处理汽车的数据,你可以创建一个包含相关变量的汽车类,如最高速度、名称、颜色和适当的方法,例如drive(double distance)或类似的东西。

如果您不想要该类的不同对象并且在多个点需要相同的行为,您可以通过多种方式防止多个实例:如果所有点都在您的 中Form1,您只需将您的类作为类成员实例化一次,然后您可以在Form1全班使用。如果您需要从不同的类访问它,您可以拥有一个全局变量(大多数人认为这是不好的做法)或创建您需要访问的类static- 这样,您根本不需要实例化它。

如果您的应用程序非常小,您可能会将其全部放在Form1课堂上,但正如您自己注意到的那样,它很快就会变得混乱和混乱。将类视为对代码进行排序的机会。想想什么与什么相关联,以及你期望一起找到什么,然后把这些东西放在课堂上。如果你坚持这一点,你最终得到的代码不会那么令人沮丧,并且具有清晰和合乎逻辑的结构。一旦事情变得更复杂,您就可以利用继承之类的东西,并且您可以重用执行不同应用程序中可能需要的事情(再次,例如数据库)的类。

这是一个非常简短且非常粗略的描述。我自己不知道任何关于该主题的好书(除了那些面向完全编程初学者的书籍,这在这里似乎不合适),但我建议在 OOP 上找到一本或搜索关于该主题的好的介绍文章。就个人而言,我发现 CodeProject 是一个很好的文章来源。这是关于 OOP 的一个

于 2012-09-05T09:32:18.033 回答
4

我使用单一职责原则作为设计类的指南。这是一个很好的讨论,重点是:

关键是每个类都应该实现一组有凝聚力的相关功能。遵循单一职责原则的一个简单方法是不断问自己一个类的每个方法和操作是否与该类的名称直接相关。如果您发现某些方法与类名不符,则应考虑将这些方法移至另一个类。

考虑到这一点,我认为您将示例应用程序的功能拆分为单独的类是正确的。否则,您最终会得到一个具有多种职责的综合 Form1 类:读取配置值、连接到数据库、读取数据。正如您所观察到的,将代码拆分为单独的类也使程序更易于理解和导航。

于 2012-09-05T09:13:34.117 回答
0

想想你的类封装了某种功能。在您的情况下,SQLConn 正在处理与数据库的连接,这意味着此类拥有数据库连接,并且所有流量现在都应该通过此类。这也意味着您的 myDataSet 类应该使用您的 SQLConn 类进行所有通信,因此在其中实例化 SqlCommand是错误的。

我认为您可能会将实例与实现中的类混淆。您正在创建 SQLConn 类的多个实例,首先是在连接到数据库的 OnLoad 方法上,然后在 myDataSet 类中创建。这类的实例不同。因此,您的 myDataSet 类将使用尚未连接到数据库的 SQLConn。

您可以通过为 myDataSet 类提供您希望它工作的 SQLConn实例来共享同一个实例:

public myDataSet(SQLConn conn) 
{ 
    SQLConn sql = conn;
} 

{
    SQLConn conn = new SQLConn();
    conn.createConnection(...);
    myDataSet ds = new myDataSet(conn);
}

这仍然不是一个好的设计,但它说明了如何传递实例与直接引用类。

于 2012-09-05T09:24:01.870 回答