Когда использовать классы в C#?
Я относительно новичок в языке C#, однако с большой помощью Google searches и Stack Overflow я уже сделал ряд приложений, которые включают работу с Office, системными службами, процессами, WMI, SQL, Linq и Active Directory...
хотя, несмотря на успех с получением этих приложений функциональным я все еще не уверен во многих вещах на языке C#, таких как хорошая практика кода и использование многих ключевых слов и т. д..
классы C#; я знаю, что я могу сделать с ними, я знаю о конструкторах и деструкторах, экземплярах и свойствах, но я не уверен в , когда Я должен использовать их. До сих пор я писал все моего кода в моем Form1.cs-файл внутри разных методов. Эти методы делают ряд различных вещей с совершенно разными API. Это, очевидно, означает, что пытаться поддерживать этот код может стать довольно сложным, и я нахожу его все более разочаровывающим найти что-то внутри меня Форма form1.цезий.
мой вопрос к вам, ребята, должен ли я разбивать свой код на разные классы? Я попытался разделить материал, связанный с SqlConnection и SqlCommands на отдельный класс, но без создания экземпляра того же класса несколько раз в моей Form1.cs я не вижу, что это легче или какая-то польза.
Я пытался собрать новое приложение вместе, но на этот раз сохраняя функциональность в своем собственном классе, я надеялся, что кто-то может сказать мне, что я глупый и делать это неправильно или, по крайней мере, дать мне какое-то руководство.
Это приложение в конечном итоге загрузит мою строку подключения из приложения.Сконфигурируйте, подключитесь к базе данных SQL и заполните набор данных несколькими таблицами из базы данных. Это никоим образом не функционально, поскольку я не могу обойти всю проблему классов.
большое спасибо :)
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. Это не на то же самое instace класса. Таким образом, ваш класс myDataSet будет использовать SQLConn, который не подключен к базе данных.
вместо этого вы можете поделиться тем же экземпляром, предоставив класс myDataSet с SQLConn экземпляр вы хотите, чтобы он работал на:
public myDataSet(SQLConn conn)
{
SQLConn sql = conn;
}
{
SQLConn conn = new SQLConn();
conn.createConnection(...);
myDataSet ds = new myDataSet(conn);
}
Это еще не хороший дизайн, но он иллюстрирует, как пройти на экземпляр и ссылка на класс.