5

私はC#言語に比較的慣れていませんが、Google検索とStack Overflowの多くの助けを借りて、Office、システムサービス、プロセス、WMI、SQL、Linq、ActiveDirectoryの操作を含む多くのアプリをすでに実行しました。 ..

これらのアプリを機能させることに成功したにもかかわらず、コードの練習やキーワードの多くの使用など、C#言語の多くのことについてはまだわかりません。

C#クラス; 私はそれらで何ができるかを知っています。コンストラクタとデストラクタ、インスタンス化とプロパティについては知っていますが、いつそれらを使用すべきかわかりません。これまで、さまざまなメソッド内のForm1.csファイルにすべてのコードを記述してきました。これらのメソッドは、完全に異なるAPIを使用してさまざまなことを実行します。これは明らかに、そのコードを維持しようとすることは非常に困難になる可能性があり、Form1.cs内で何かを見つけることはますます苛立たしいことに気づいていることを意味します。

皆さんへの私の質問は、コードを異なるクラスに分割する必要があるかどうかです。SqlConnectionとSqlCommandsに関連するものを別のクラスに分割しようとしましたが、Form1.csで同じクラスを複数回インスタンス化せずに、これが簡単でメリットがあるとは思えません。

私は新しいアプリをつなぎ合わせようとしてきましたが、今回は独自のクラスで機能を維持しているので、誰かが私が愚かで間違っていると言ってくれるか、少なくともいくつかのガイダンスを教えてくれることを望んでいました。

このアプリは、最終的にApp.Configから接続文字列をロードし、SQLデータベースに接続して、データベースの複数のテーブルをDataSetに入力します。クラスの問題全体に頭を悩ませることはできないので、これは決して機能的ではありません。

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のもののように、独自のクラスにグループ化されるように、可能な限り分割する必要があると言っています。もう1つのよく使用される例は、車の例です。車のデータを処理する必要がある場合は、最高速度、名前、色、およびたとえばそのような適切なメソッドなどの関連変数を含む車のクラスを作成しますdrive(double distance)

そのクラスの異なるオブジェクトが必要でなく、複数のポイントで同じ動作が必要な場合は、いくつかの方法で複数のインスタンスを防ぐことができます。すべてのポイントがにある場合はForm1、クラスメンバーとしてクラスをインスタンス化する必要があるのは1回だけです。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 に答える