Когда использовать классы в C#?

Я относительно новичок в языке C#, однако, благодаря большой помощи от поиска в Google и переполнения стека, я уже создал ряд приложений, которые включают работу с Office, системными службами, процессами, WMI, SQL, Linq и Active Directory...

Хотя, несмотря на успех в получении этих приложений, я все еще не уверен во многих вещах на языке C#, таких как хорошая практика кода и использование многих ключевых слов и т. Д.

C# классы; Я знаю, что я могу с ними сделать, я знаю о Конструкторах и Деструкторах, Instantiation и Properties, но я не уверен, когда мне следует их использовать. До сих пор я написал весь свой код в своем файле 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;
    }
}

3 ответа

Решение

Принципы, лежащие в основе ООП, говорят более или менее о том, что вы должны как можно больше разбивать вещи, чтобы связанные вещи группировались в своем собственном классе, как, например, вещи SQL в вашем примере. Другой, часто используемый пример - это автомобиль - если вам нужно иметь дело с данными об автомобилях, вы должны создать класс автомобиля, содержащий соответствующие переменные, такие как максимальная скорость, имя, цвет и соответствующие методы, например, например, drive(double distance) или что-то типа того.

Если вам не нужны разные объекты этого класса и вам нужно одинаковое поведение в нескольких точках, вы можете предотвратить несколько экземпляров несколькими способами: если все точки находятся в вашем Form1вам нужно создать экземпляр вашего класса только один раз, и вы можете использовать его на протяжении всего Form1 учебный класс. Если вам нужен доступ к нему из разных классов, вы можете либо иметь глобальную переменную (что большинство считают плохой практикой), либо создать класс, к которому вам нужен доступ static - таким образом, вам вообще не нужно создавать его экземпляр.

Если ваше приложение действительно маленькое, вы можете оставить все это в своем Form1 класс, но, как вы сами заметили, он может очень быстро запутаться и запутаться. Думайте о классах как о возможности сортировать ваш код. Подумайте о том, что с чем связано, и что вы ожидаете найти вместе, и поместите эти вещи в классы. Если вы будете придерживаться этого, вы в конечном итоге получите код, который будет менее расстраивающим, и который имеет четкую и логичную структуру. Вы можете использовать преимущества таких вещей, как наследование, когда все становится более сложным, и вы можете повторно использовать классы, которые делают вещи (опять же, например, базы данных), которые могут вам понадобиться в разных приложениях.

Это очень краткое и очень грубое описание. Я сам не знаю хороших книг по этой теме (кроме тех, которые предназначены для начинающих программистов, что здесь неуместно), но я предлагаю найти одну из них по ООП или найти хорошие вводные статьи по этой теме. Лично я считаю CodeProject хорошим источником статей. Вот один на ООП.

Я использую принцип единой ответственности в качестве руководства для разработки классов. Вот хорошее обсуждение этого, с существенным моментом:

Дело в том, что каждый класс должен реализовывать связный набор связанных функций. Простой способ следовать принципу единой ответственности - постоянно задавать себе вопрос, связан ли каждый метод и операция класса с именем этого класса. Если вы найдете некоторые методы, которые не соответствуют имени класса, вам следует рассмотреть возможность перемещения этих методов в другой класс.

Имея это в виду, я думаю, что вы правы, разделив функциональность вашего примера приложения на отдельные классы. В противном случае вы получите конгломератный класс Form1, который обладает множеством обязанностей: чтение значений конфигурации, подключение к базам данных, чтение данных. Как вы заметили, разделение кода на отдельные классы также облегчает понимание и навигацию программы.

Подумайте о своих классах, инкапсулирующих какую-то функциональность. В вашем случае 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);
}

Это все еще не очень хороший дизайн, но он показывает, как передать экземпляр вместо прямой ссылки на класс.

Другие вопросы по тегам