C# — Помогите с кодом C#


Содержание

Добро пожаловать на ИТ форум!

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

Помогите разобраться с кодом C#

    Автор темы Sequd Дата начала 24.08.2009

Sequd

New Member

мол не правельный адрес или чет такое. пробовал писать по разному, мож чет не так делаю?
и объяснить если можите как потом вызвать этот код с Веб страницы при нажатии на кнопку скажем «Edit» . и вообще вопрос, можно же использовать XML для хранения обычного текста?)

Люди добрые, помогите пожалуйста в изучении языка програмирования для веб сайтов и веб приложений. есть огромнуе желание в изучении, но без помощи не получаеца. читаю книги, но мало что понимаю(
я думаю, что для знающего человека не составит труда уделить 15-20 минут в день, для помощи. например давать простые задания, объяснять чтото. если кто решится помочь, вот моя ася 416584550. буду очень благодарен, в заранее спасибо.

Соглашения о написании кода на C# (Руководство по программированию на C#) C# Coding Conventions (C# Programming Guide)

Соглашения о написании кода предназначены для реализации следующих целей. Coding conventions serve the following purposes:

Создание согласованного вида кода, позволяющего читателям сосредоточиться на содержимом, а не на структуре. They create a consistent look to the code, so that readers can focus on content, not layout.

Предоставление читателям возможности делать предположения, основанные на опыте, и поэтому быстрее понимать код. They enable readers to understand the code more quickly by making assumptions based on previous experience.

Упрощение процессов копирования, изменения и обслуживания кода. They facilitate copying, changing, and maintaining the code.

Предоставление лучших методик C#. They demonstrate C# best practices.

Майкрософт использует приведенные в этом разделе рекомендации для разработки примеров и документации. The guidelines in this topic are used by Microsoft to develop samples and documentation.

Соглашения об именах Naming Conventions

В коротких примерах, не содержащих директив using, рекомендуется использовать полные указания для пространства имен. In short examples that do not include using directives, use namespace qualifications. Если известно, что пространство имен импортировано в проект по умолчанию, не требуется указывать полные имена из этого пространства имен. If you know that a namespace is imported by default in a project, you do not have to fully qualify the names from that namespace. Полные имена, если они слишком длинные для одной строки, можно разбить после точки (.), как показано в следующем примере. Qualified names can be broken after a dot (.) if they are too long for a single line, as shown in the following example.

Нет необходимости изменять имена объектов, созданных с помощью инструментов разработки Visual Studio, чтобы привести их в соответствие с другими соглашениями. You do not have to change the names of objects that were created by using the Visual Studio designer tools to make them fit other guidelines.

Соглашения о расположении Layout Conventions

Чтобы выделить структуру кода и облегчить чтение кода, в хорошем макете используется форматирование. Good layout uses formatting to emphasize the structure of your code and to make the code easier to read. Примеры и образцы корпорации Майкрософт соответствуют следующим соглашениям. Microsoft examples and samples conform to the following conventions:

Использование параметров редактора кода по умолчанию (логичные отступы, отступы по четыре символа, использование пробелов для табуляции). Use the default Code Editor settings (smart indenting, four-character indents, tabs saved as spaces). Дополнительные сведения см. в разделе «Параметры», «Текстовый редактор», C#, «Форматирование». For more information, see Options, Text Editor, C#, Formatting.

Запись только одного оператора в строке. Write only one statement per line.

Запись только одного объявления в строке. Write only one declaration per line.

Если отступ для дополнительных строк не ставится автоматически, необходимо сделать для них отступ на одну позицию табуляции (четыре пробела). If continuation lines are not indented automatically, indent them one tab stop (four spaces).

Добавление по крайней мере одной пустой строки между определениями методов и свойств. Add at least one blank line between method definitions and property definitions.

Использование скобок для ясности предложений в выражениях, как показано в следующем коде. Use parentheses to make clauses in an expression apparent, as shown in the following code.

Соглашения о комментариях Commenting Conventions

Комментарий размещается на отдельной строке, а не в конце строки кода. Place the comment on a separate line, not at the end of a line of code.

Текст комментария начинается с заглавной буквы. Begin comment text with an uppercase letter.

Текст комментария завершается точкой. End comment text with a period.

Между разделителем комментария (/ /) и текстом комментария вставляется один пробел, как показано в следующем примере. Insert one space between the comment delimiter (//) and the comment text, as shown in the following example.

Вокруг комментариев не должно быть звездочек. Do not create formatted blocks of asterisks around comments.

Рекомендации по работе с языком Language Guidelines

В следующих подразделах описаны методики, которыми руководствуется команда C# для подготовки примеров и образцов кода. The following sections describe practices that the C# team follows to prepare code examples and samples.

Тип данных String String Data Type

Для сцепления коротких строк рекомендуется использовать интерполяцию строк, как показано в следующем коде. Use string interpolation to concatenate short strings, as shown in the following code.

Для добавления строк в циклы, особенно при работе с текстами больших размеров, рекомендуется использовать объект StringBuilder. To append strings in loops, especially when you are working with large amounts of text, use a StringBuilder object.

Неявно типизированные локальные переменные Implicitly Typed Local Variables

В случаях, когда тип переменной понятен из правой части назначения или когда точный тип не важен, рекомендуется использовать неявное типизирование для локальных переменных. Use implicit typing for local variables when the type of the variable is obvious from the right side of the assignment, or when the precise type is not important.

Если тип из правой части назначения не является очевидным, не рекомендуется использовать var. Do not use var when the type is not apparent from the right side of the assignment.

При указании типа переменной не следует полагаться на имя переменной. Do not rely on the variable name to specify the type of the variable. Имя может быть неверным. It might not be correct.

Рекомендуется избегать использования var вместо dynamic. Avoid the use of var in place of dynamic.

Рекомендуется использовать неявное типизирование для определения типа переменной цикла в циклах for и foreach. Use implicit typing to determine the type of the loop variable in for and foreach loops.

В следующем примере неявное типизирование используется в операторе for . The following example uses implicit typing in a for statement.

В следующем примере неявное типизирование используется в операторе foreach . The following example uses implicit typing in a foreach statement.

Беззнаковый тип данных Unsigned Data Type

  • Как правило, рекомендуется использовать int вместо беззнаковых типов. In general, use int rather than unsigned types. В C# обычно используется int . Использование int упрощает взаимодействие с другими библиотеками. The use of int is common throughout C#, and it is easier to interact with other libraries when you use int .

Массивы Arrays

При инициализации массивов в строке объявления рекомендуется использовать сокращенный синтаксис. Use the concise syntax when you initialize arrays on the declaration line.

Делегаты Delegates

Для создания экземпляров типа делегата рекомендуется использовать сокращенный синтаксис. Use the concise syntax to create instances of a delegate type.

Операторы try-catch и using в процессе обработки исключений try-catch and using Statements in Exception Handling

Рекомендуется использовать оператор try-catch для обработки большей части исключений. Use a try-catch statement for most exception handling.

Использование оператора C# using упрощает код. Simplify your code by using the C# using statement. При наличии оператора try-finally, код которого в блоке finally содержит только вызов метода Dispose, вместо него рекомендуется использовать оператор using . If you have a try-finally statement in which the only code in the finally block is a call to the Dispose method, use a using statement instead.

Операторы && и || && and || Operators

Чтобы избежать возникновения исключений и увеличить производительность за счет пропуска необязательных сравнений, рекомендуется использовать && вместо & и || вместо | при выполнении сравнений, как показано в следующем примере. To avoid exceptions and increase performance by skipping unnecessary comparisons, use && instead of & and || instead of | when you perform comparisons, as shown in the following example.

Оператор New New Operator

Рекомендуется использовать сокращенную форму создания экземпляра для объекта с неявным типизированием, как показано в следующем объявлении. Use the concise form of object instantiation, with implicit typing, as shown in the following declaration.

Предыдущая строка соответствует следующему объявлению. The previous line is equivalent to the following declaration.

Рекомендуется использовать инициализаторы объектов для упрощения создания объектов. Use object initializers to simplify object creation.

Обработка событий Event Handling

При определении обработчика событий, которого не требуется удалять позднее, рекомендуется использовать лямбда-выражение. If you are defining an event handler that you do not need to remove later, use a lambda expression.

Статический члены Static Members

  • Для вызова статических членов следует использовать имя класса: ClassName.StaticMember. Call static members by using the class name: ClassName.StaticMember. В этом случае код становится более удобочитаемым за счет четкого доступа. This practice makes code more readable by making static access clear. Не присваивайте статическому члену, определенному в базовом классе, имя производного класса. Do not qualify a static member defined in a base class with the name of a derived class. Во время компиляции кода его читаемость нарушается, и если добавить статический член с тем же именем в производный классе, код может быть поврежден. While that code compiles, the code readability is misleading, and the code may break in the future if you add a static member with the same name to the derived class.

Запросы LINQ LINQ Queries

Используйте значимые имена для переменных запроса. Use meaningful names for query variables. В следующем примере используется seattleCustomers для клиентов, находящихся в Сиэтле. The following example uses seattleCustomers for customers who are located in Seattle.

Рекомендуется использовать псевдонимы для уверенности в том, что в именах свойств анонимных типов верно используются прописные буквы при помощи правил использования прописных и строчных букв языка Pascal. Use aliases to make sure that property names of anonymous types are correctly capitalized, using Pascal casing.

Переименуйте свойства, если имена свойств в результате могут быть неоднозначными. Rename properties when the property names in the result would be ambiguous. Например, если запрос возвращает имя клиента и идентификатор распространителя, не оставляйте имена в виде Name и ID , а переименуйте их, чтобы было ясно, что Name — имя клиента и ID — идентификатор распространителя. For example, if your query returns a customer name and a distributor ID, instead of leaving them as Name and ID in the result, rename them to clarify that Name is the name of a customer, and ID is the ID of a distributor.

Рекомендуется использовать неявное типизирование в объявлении переменных запроса и переменных диапазона. Use implicit typing in the declaration of query variables and range variables.

Выравнивайте предложения запроса под предложением from, как показано в предыдущих примерах. Align query clauses under the from clause, as shown in the previous examples.

Чтобы гарантировать, что более поздние предложения запроса работают с ограниченным, отфильтрованным набором данных, используйте предложение where перед другими предложениями запроса. Use where clauses before other query clauses to ensure that later query clauses operate on the reduced, filtered set of data.

Используйте несколько предложений from для доступа к внутренним коллекциям вместо предложения join. Use multiple from clauses instead of a join clause to access inner collections. Например, коллекция объектов Student может содержать коллекцию результатов тестирования. For example, a collection of Student objects might each contain a collection of test scores. При выполнении следующего запроса возвращаются результаты, превышающие 90 балов, а также фамилии учащихся, получивших такие оценки. When the following query is executed, it returns each score that is over 90, along with the last name of the student who received the score.

Безопасность Security

Следуйте указаниям, изложенным в правилах написания безопасного кода. Follow the guidelines in Secure Coding Guidelines.

Генератор поставщиков данных. Пример независимого кода

В статье «ADO.Net. Элементы теории» отмечалось, что двумя основными компонентами ADO.NET для доступа к данным и их обработки являются поставщики данных .NET Framework и DataSet. На примере реляционной модели БД будет показано, как создать единую кодовую базу с помощью обобщенных типов доступа к данным (библиотека System.Data.Common) и конфигурационных файлов. В примере используется БД автотранспортного предприятия Garage из статьи «Создание базы данных SQL Server«.

В примере «Продажа билетов в кинотеатре» для источника подключения — «Файл базы данных Microsoft Access» доступен единственный поставщик данных — .Net Framework для OLE DB. Для работы с БД на основе SQL Server необходим поставщик данных SqlClient, для других источников данных потребуется Odbs. Возможно ли написать код программы, независимый от конкретного поставщика? Ведь в библиотеке System.Data.Common содержится описание классов, наследуемых в библиотеках System.Data.SqlClient, System.Data.OleDb и System.Data.Odbc.

Постановка задачи

Используя файл конфигурации App.config и сборку System.Configuration, а также классы библиотеки System.Data.Common написать приложение, в котором явно не указывается конкретный поставщик данных.

Решение

1) Создадим в Visual Studio 2020 Community консольное приложение ГенераторПоставщиковДанных. Добавим сразу оператор using System.Data.Common;

2) Добавим оператор using System.Configuration;
Примечание. Рекомендуется проверить наличие ссылки на эту сборку, для чего выберите Проект/Добавить ссылку, после чего в окне «Менеджер ссылок» отметить позицию System.Configuration и нажать Ok.

3) Откройте для редактирования файл App.config (Если его нет в вашем проекте, добавьте его: Проект/Добавление нового элемента/Файл конфигурации приложения). В редакторе кода App.config добавьте элемент с двумя ключами (key): «provider» со значением «System.Data.SqlClient» и «conStr» с указанием подключения к базе данных Garage (см. предыдущий пример). Подключение к БД получите через Обозреватель объектов SQL Server, кликнув правой кнопкой на БД Garage, и в окне Свойства объекта Garage скопируйте строку подключения, у меня, например:
Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Garage;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False

Текст файла App.config:

Теперь все необходимое находится в файле конфигурации. Понятно, что при смене провайдера изменится первая строка в , а при смене БД — вторая строка и только!

4) Перейдем к редактированию Program.cs. В метод Main( ) добавим три оператора:

Класс System.Data.Common.DbProviderFactory представляет набор методов для создания экземпляров реализации поставщика для классов источника данных. Метод GetFactory( ) возвращает экземпляр класса. Далее нам будет нужны только генератор поставщика df и строка подключения cnStr.

5) Зададимся целью прочитать содержимое трех таблиц БД Garage: Cars, Drivers, Routes. Для этого нам понадобятся объекты трех классов DbConnection, DbCommand и DbDataReader из библиотеки System.Data.Common. Используем вложенную конструкцию using < >, упомянутую в конце статьи «Сборка мусора и финализаторы«. Напомним, что конструкция упрощает работу с объектами, которые реализуют интерфейс IDisposable. Интерфейс IDisposable содержит один метод .Dispose(), который используется для освобождения ресурсов,
которые захватил объект.

Тогда полный текст Program.cs:

Результат:

Первые три строки содержат информацию по объектам «подключение», «команда» и «чтение данных».

Вывод. Поставленная задача написания независимого (от типа БД) кода выполнена.

В следующей статье «Примеры SQL-запросов. Microsoft SQL Server и язык T-SQL» описаны действия по удалению, вставке и изменению записей в таблицах БД .

Нехитрые Советы для программиста C#

1. Довольно часто нужно вернуть в коде истину , если число положительное , и ложь , если число отрицательное. Тогда , вместо того , чтобы писать что-то вроде этого :

public static bool TruOrFls (int i )

. можно написать такой простой код :

public static bool TruOrFls( int i)

2. Для определения , является ли целое число чётным или нечётным , можно использовать сл. метод :

public static bool IsNechet( int i)

Math .DivRem(i, 2, out result);

3. Простой класс для Шаблона «Одиночка » (Singleton) для создания форм :

public static class SingletonForm

private static Dictionary Type , Form > forms = new Dictionary Type , Form >();

public static Form ShowInstance( Type t)

Form f = ( Form ) Activator .CreateInstance(t);

f.Disposed += new EventHandler (f_Disposed);

static void f_Disposed( object sender, EventArgs e)

public void btnsprTIP_Click(System. Object sender, System. EventArgs e)

SingletonForm .ShowInstance( typeof ( frmMyForm ));

4 . Для «отлавливания» неверно введённого символа в сетке( DataGr >можно использовать событие DataError :

public void MyDtg_DataError( object sender, DataGridViewDataErrorEventArgs anError)

int ColIndx = ( int )anError.ColumnIndex;

string ColHT = MyDtg.Columns[ColIndx].HeaderText;

Utils .Mess( » » + ColHT + » !» );

5. Помещайте формы , классы , отчёты и т д. проекта в соответствующие подкаталоги с именами , например , FRM, CLS, RPT и т.д. Такая систематизация существенно облегчит вашу жизнь при работе с большими проектами. Мешанина из классов , форм , отчётов и пр. в одном подкаталоге вряд ли пойдёт на пользу качеству вашего проекта.

6. Если нужно постоянно обращаться к какому-то объекту ( или что-то возвращать из метода без передачи параметра внутрь его) , то такую функцию удобно осуществлять с помощью аксессора get . Например , сл. код возвращает текущую строку в DataGrid View:

public DataGridViewRow GetCurrentRowOb

К такому методу можно обращаться просто как к переменной.

7. Вы можете назначить свою обработку какого-либо события в конструкторе сл. образом :

/* Альтернативная обработка события */

this .txtHr.KeyPress += new KeyPressEventHandler ( this .ObrabKey);

В приведённом примере назначаем метод обработки ObrabKey событию KeyPress

8. Технология LINQ может существенно сократить количество ваших клацаний по клавиатуре. Например сл. код возвращает отсортированный массива :

public static string [] GetStr

public static IEnumerable string > SortedList

Цукерберг рекомендует:  Вывод альтернативной картинки при отключенном флэш.

IEnumerable string > sort = GetStr.OrderBy(a => a.j);

9. Несложные классы (особенно если используется их большое количество экземпляров) лучше оформлять в виде структур — ключевое слово struct . Структура , в отличии от класса , является значимым типом. Экономия ресурсов , в этом случае , может оказаться весьма существенной.

10 . Довольно часто приходиться итерировать объекты , которые не поддерживают интерфейс IEnumarable. Чтобы избежать это ограничение , существует специальная конструкция — yeild. Ниже приведён пример , как можно проитерировать коллекцию упр. элементы на главной форме :

class Num : IEnumerable

frmMain MyF = GlobalVar .MainForm;

public System.Collections. IEnumerator GetEnumerator()

yield return MyF.Panel1;

yield return MyF.Panel2;

yield return MyF.Panel3;

yield return MyF.panel6;

yield return MyF.GroupBox1;

yield return MyF.groupBox2;

yield return MyF.GroupBox3;

yield return MyF.TableLayoutPanel1;

yield return MyF.pictureBox1;

Вот теперь можно пробежаться в цикле -применение в вызывающей стороне :

foreach ( Control cob in new Num ())

cob.Anchor = AnchorStyles .Right;

11. Использование конструкции using ( . ) < . >гарантирует применение метода . Dispose() — освобождение объекта , например :

using ( SqlCommand cmd = new SqlCommand (strSQL, GlobalVar .conn))

// Здесь что-то делаем с объектом cmd .

// Это нужно делать , если не использовать using (. )

1 2 . При работе с базами данных обязательно напишите класс с методами создания соединения с БД и его тестированием , что-то вроде этого :

static class clsConn

public static void CreateConn( string strmydir)

GlobalVar .conn = new SqlConnection (ConnectStringBuild);

Utils .Mess( » Ошибка !» );

public static bool TestConn

using ( SqlConnection testconn = new SqlConnection (ConnectStringBuild))

return (testconn.State == ConnectionState .Open);

// Создание строки подключения к БД .

public static string ConnectStringBuild

string s = «Data Source=» + My. Settings .Default.ServerName + @»\» + My. Settings .Default.SQLServerName + «;» ;

return @s += «Initial Catalog=» + My. Settings .Default.BaseName + «;Integrated Security=True» ;

13. Включите обработку ошибок в стартовый модуль вашей программы. Выше него ошибка » не поднимется «( выше только Господь Бог :-). Что-то вроде этого :

sealed class mdlMain

public static void Main( string [] args)

Application .SetCompatibleTextRenderingDefault( false );

GlobalVar .MainForm = new frmMain ();

Application .Run( GlobalVar .MainForm);

catch ( ArgumentNullException ane)

MessageBox .Show(ane.Message, » Main-ArgumentNullException» );

catch ( FormatException fex)

MessageBox .Show(fex.Message, » Main-FormatException» );

catch ( NullReferenceException nre)

MessageBox .Show(nre.Message, » Main-NullReferenceException» );

catch ( InvalidCastException ice)

MessageBox .Show(ice.Message, » Main-InvalidCastException» );

catch ( Exception ex)

MessageBox .Show(ex.Message , » o Main» );

14. Если в программе постоянно приходиться обрабатывать неизменяемый массив строк , то инициализацию такого массива очень удобно оформить с помощью аксессора get ( см. Совет 6 ) , что-то вроде этого :

private static string [] GetStringArr

string [] ars = new string [] <

Тогда подсчитать , например , количество элементов в массиве очень просто :

int RecCount1 = GetStringArr.Count();

Или , обращение к j- му элементу массива :

string s = GetStringArr[j-1];

15. Довольно часто в коде нужно контролировать — является ли значение пустым , и вернуть , ну допустим , значение нуль для типа float. Осуществить такую проверку можно с помощью такого нехитрого метода :

public static float CheckIt( object par)

return ( Convert .ToSingle( Convert .IsDBNull(par) ? 0 : par));

16. Если нужно знать , в каком столбце сетки DataGridView пользователь завершил редактирование ячейки , то можно использовать событие _CellEndEdit:

public void MyDtg_CellEndEdit( object sender, DataGridViewCellEventArgs e)

// Узнаём имя столбца .

string ColName = MyDtg.Columns[e.ColumnIndex].Name;

/* Здесь что-то делаем . */

17. Чтобы ‘ пробежаться ‘ по всем контролам в панели , и отловить , ну скажем , метки ( Label ) можно использовать такой код :

foreach ( Control cob in this .panel 1 .Controls)

if (cob is Label )

/* Здесь что-то делаем с контролом типа Label */

18. К строковой переменной можно смело «приклеивать » целочисленные переменные. Среда CLR поймёт такое преобразование без метода ToString(). Это особенно бывает удобно при формировании SQL— запросов в виде строк , что-то вроде этого :

string sSQL= «Update Itogi SET Area=@area where kod=» + (i + 1);

19. ‘Склеивать’ строки лучше специально созданным для этого методом Concat для переменных типа string :

string s3 = «three» ;

// Можно делать так :

string sAll = s1+s2+s3;

// . но грамотнее так :

string sAll = string .Concat(s1,s2,s3);

20. П рограммисты как-то недооценивают удобство метода Format для строк при формировании SQL-запросов . Например, вместо того, чтобы писать что-то вроде этого:

// Можно делать так :

string strUpdate = «Update Customers SET Balance=@Balance Where Cust > + >» and Social > + SocID;

. лучше написать такой код:

string strUpdate = «Update Customers SET Balance=@Balance Where Cust >;

string strSQLUpdate = string. Format( «<0> <1>and Social >, strUpdate, ID, SocID);

21. Иногда бывает нужно узнать индекс элемента в массиве, ну например, в цикле foreach . Сделать это можно сл. образом :

// Есть массив строк .

private static string [] GetStr

string [] ars = new string [] <

// В вызывающей стороне :

// Конечно , можно использовать счётчик .

foreach ( string s in GetStr)

private static void Sub()

foreach ( string s in GetStr)

//Узнаём индекс элемент а s в массиве .

int i = Array .IndexOf(GetStr, s);

22. Везде, где можно, предпочтительнее использовать типизированные коллекции, вместо классических массивов. Основные преимущества такого подхода заключаются в двух фактах: во-первых, коллекции позволяют не заботиться о контроле за выходом индекса за установленный размер ( пресловутое Index Out of Range), а во-вторых, в них можно хранить (в отличии от нетипизированных списков) элементы одного типа. Итак, вместо использования скажем:

string [] ars = new string [6];

. предпочтительнее использовать типизированный список List string >:

List string > ars = new List string >();

Небольшая ремарка. Вообще , на мой взгляд , в связи с появлением начиная , по-моему , с . NET Framework 2.0 типизированных коллекций , классические массивы можно считать коллекциями устаревшего типа по причинам , указанным выше

23. Если в метод надо передавать много-много всяких входных параметров, то вместо такого «баяна» предпочтительнее передавать структуру.

Например, вместо использования некоего метода XYZ

static void XYZ( int a, int b, int c, string d, string e)

. .. можно сначала определить структуру:

public string d,e;

public ABC ( int _a, int _b, int _c, string _d, string _e)

a=_a; b=_b; c=_c; d=_d; e=_e;

. а затем передавать её в метод :

static void XYZ( ABC mystru)

Вызов такого метода станет гораздо более изящным:

/* Определяем экземпляр структуры ABC */

ABC MyStru = new ABC (1,2,3,»one», «two»);

/*Вызываем метод XYZ */

24. Довольно часто программисты пользуются методом Parse для конвертации строковых величин в другие типы, что-то вроде этого:

int j= int .Parse (MyVal.ToString());

Однако, в случае неудачи такой метод выбросит исключение. Для написания устойчивого кода предпочтительнее пользоваться метод TryParse, приблизительно так:

/* Вернёт значение j=0, даже если метод TryParse потерпит неудачу */

bool bVal = int .TryParse(MyVal.ToString(), out j);

25 . Самый подходящий элемент для отображения содержания базы данных — это конечно же DataGr >, упрощенно говоря, сетка данных . Но после завершения редактирования данных пользователем в такой сетке встаёт задача — как передать изменения в базу данных ? Одно из решений такой задачки состоит в переписывании (в цикле естественно) значений ячеек сетки DataGridViewCell в значения объекта DataRow , привязанного к сетке объекта DataTable набора данных DataSet . Тут, правда, надо хорошо разбираться в идеологии объектной модели доступа к данным ADO. NET . Затем значения DataRow конкретного столбца переписываем SQL-конструкцией Update непосредственно в базу данных. Все циклы здесь можно прогонять конструкцией foreach

26 . Иногда возникает сл. ситуация. На форме есть куча однотипных элементов WinForms, одно и тоже событие которых обрабатывается одинаково. Как пример, есть несколько элементов TextBox, для которых событие, ну скажем, KeyPress обрабатывается одним и тем же методом.

Тогда, вместо такого забойного кода . :

public void txt box1 _KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

public void txt box 2_KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

public void txt boxN _KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

. можно сначала определить массив TextBox’ов :

private TextBox [] RetTBox

. а затем, скажем в конструкторе формы, прокрутить такой цикл :

/* Добавляем свой обработчик контроля нажатия клавиш */

foreach ( TextBox tb in RetTBox)

tb.KeyPress += new KeyPressEventHandler (ObrabKeyPress);

27 . У объекта ADO.Net Reader есть один весьма полезный метод — HasRows. Он возвращает значение true , если в запросе есть данные.

Проконтролировать наличие ‘ пустого ‘ Reader’ а в это случае становиться довольно легко :

using ( SqlCommand SelCustoms = new SqlCommand (sSel, conn2))

//Нет записей о заказчиках ! Прекращаем читать ..

// Пробежимся по всем записям Заказчиков .

// . Здесь что-то читаем Reader’ом

28 . Хорошей альтернативой созданию параметров в простых SQL- запросах ( объект Parameters) может стать использование строки запроса методом string .Format ( см. Совет 20 ) , что-то вроде этого :

string sSQL = string .Format( «Select * From Customers where Customer >, CustID);

SqlCommand cmd = new SqlCommand (sSQL, conn2)

Объём кода при этом значительно сокращается — необходимость описывать параметр , его тип и значение просто отпадает.

2 9 . Приступая к созданию своего первого более-менее сложного проекта , не забудьте создать класс для размещения в нём всевозможных мелких вспомогательных утилит. Фактически , наличие такого класса (как правило с именем Utils ), стало стандартом для проектирования информационных систем на С #. Получиться что-то вроде аналог ящика для инструментов , из которого вы сможете время от времени доставать нужное (по контексту ситуации) приспособление.

30 . Создание глобальных переменных , видимых из любой части программы , является одним из стандартных положений для разработчика любого уровня . Чаще всего , такая необходимость связана с использованием каких-то глобальных настроек программы. Одним из решений этой задачи является использование настроек — пространство имён My. Setting . Тогда достаточно будет написать , ну скажем в классе Utils ( см. Совет 29 ) , простой метод для ‘ выдёргивания ‘ значения этой настройки , что-то вроде этого (в приведённом ниже примере , если уж рассматривать совсем конкретный случай , просто взят год , принятый по умолчанию) :

public static int GetGodSetting

return ( int .Parse)(My.Settings. Default .god);

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

int God = Utils .GetGodSetting;

31 . При использовании сложных классических WinForms, старайтесь не перегружать код формы. Например , если на форме есть много кнопок , нажатие которых надо обрабатывать , вместо такого кода (особенно если он забойный) . :

public void Btn1_Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку Btn1

public void Btn 2 _Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку Btn 2

public void BtnN_Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку BtnN

. можно создать класс ну скажем clsClickBtn , в который вынести все методы обработки при нажатии на кнопку , а в конструкторе формы разместить сл. код :

Btn1.Click += new EventHandler ( clsClickBtn .Btn1_Click);

Btn2.Click += new EventHandler ( clsClickBtn .Btn2_Click);

BtnN.Click += new EventHandler ( clsClickBtn .BtnN_Click);

Код формы в этом случае может сильно ‘ похудеть ‘ .

04. 12 .2013 , г. Юрьевец

32 . Ещё один подход к обозначенной в п. 31 проблеме может быть следующий.

Сначала создаём структуру ну допустим для обработки нажатий на гиперссылку LinkLabel :

public LinkLabel l;

public LinkLabelLinkClickedEventHandler h;

public struLL( LinkLabel _l, LinkLabelLinkClickedEventHandler _h)

Далее создаём список из обозначенной выше структуры , что-то вроде такого :

private List struLL > GetLLList

List struLL > opList = new List struLL >();

opList.Add( new struLL (lL _ A, clsLLblClick .MethodA));

opList.Add( new struLL (lL _ B, clsLLblClick .MethodB));

opList.Add( new struLL (lL _ Z, clsLLblClick .MethodZ));

Для инициализации методов обработки при нажатии на гиперссылки (в случае нашего примера) осталось только в конструкторе формы прокрутить такой цикл :

foreach ( struLL ll in GetLLList)

3 3 . Каким образом можно проитерировать управляющие элементы (контролы в просторечии) на форме ? Один из подходов описан в Совете 26 . Но существует ещё одно решение , пожалуй даже более изящное и простое. Заключается оно в том , что нужные контролы просто помещаем на форме в какой-либо контейнер , типа Panel . В этом случае в конструктор формы помещаем такой простой код (как пример для Кнопок — объект Button ) для обработки нажатий :

// Цикл по кнопкам в панели 1 .

foreach ( Button btn in panel 1 .Controls)

btn.Click += new EventHandler (btnClik);

34. При работе со справочниками часто требуется вернуть значение кода (ключа) по значению описания ключа. Конечно , можно для решения такой задачки создать структуру с двумя полями. Но гораздо проще воспользоваться одной из уже существующих коллекций — например словарем Dictionary . Тогда указанный подход можно продемонстрировать на сл. примере.

Создаем следующий метод :

public static int ReturnKodTown( string s)

Dictionary int, string > DicTowns = new Dictionary int, string >();

DicTowns.Add( 2 , » Санкт-Петербург » );

DicTowns.Add( 3 , » Казань » );

DicTowns.Add( 4 , » Новосибирск » );

DicTowns.Add( 5 , » Краснодар » );

return DicTowns.First(a => a.Value == s).Key;

Теперь узнать код города для нашего примера очень легко :

string gorod = » Новосибирск » ;

int kod = ReturnKodTown (gorod);

35. При использовании параметризованных SQL- запросов предпочтительнее пользоваться более современным методом . AddWithValue вместо .Add. Указывать тип поля при таком подходе не обязательно , нужно только указать параметр и его значение :

var myCMD = new SqlCommand (strInsSvod, GlobalVar.conn)

var pars = myCMD.Parameters;

// Используем метод AddWithValue

pars.AddWithValue( «@myPar» , myVal);

36. В развитии темы использования более рациональных подходов создания параметризованных запросов ( Совет 35 ). У коллекции параметров Parameters объекта Command есть ещё один полезный метод , позволяющий загрузить п a раметры в запрос массивом. Называется он . AddRange :

// Готовим массив параметров .

private static SqlParameters [] GetMyPars

new SqlParameter ( «@par2» , myVal2)),

new SqlParameter ( «@parN» , myValN))

// Использование метода . AddRange

using ( var cmd = new SqlCommand (s, GlobalVar.conn))

var pc = cmd.Parameters;

3 7 . При инициализации коллекций типа List вместо такого кода :

List string > MyList = new List string >();

MyList. Add( » один » ) ;

. можно использовать более короткую эквивалентную запись :

3 8 . При работе с коллекциями иногда хотелось бы не только проитерировать их в одном операторе , но и совершить какую-то обработку. В качестве примера , предположим , что есть массив :

. и для значений массива меньше или равно 5 , нужно умножить на 2 , а для более 5 умножить на 3.

Здесь на помощь может придти делегат Func и блочный лямбда-оператор. Что-то вроде этого ( понятное дело , блочный лямбда-оператор может быть много сложнее и состоять не из одной строки , как в случае нашего простенького примера) :

Func int , int , int > myFunc = (z, y) => <

return ( z y) ? 2 * z : 3 * z ;

Теперь , чтобы получить массив обработанных значений gruppa , можно написать такой простой код одной строчкой ( никакого foreach не нужно ! ) :

var gruppa = myInt.Select(a => myFunc(a, 5)).ToArray();

10 .01. 2015 , г. Обнинск

40. Назначить свой обработчик событий, скажем, для ввода данных в TextBox можно еще и с использование лямбда-оператора сл. образом ( м етод MyObrabKeyPress ) :

textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);

Тогда , даже можно создать свой метод для обработки нажатий в нескольких контролах , что-то вроде такого :

textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBox2.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBox3.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBoxN.KeyPress += (o, e) => MyObrabKeyPress( o, e);

Затем , такой метод лучше всего поместить в конструктор формы , на которой расположены наши контролы ( TextBox’ ы для случая нашего примера) :

41. Тем , кто создает приложения для работы с базами данных, случается иметь дело с весьма ‘забойными’ SQL-запросами, которые могут занять десятки строчек кода. Но хранить такие запросы в тексте программы, несмотря на определенное удобство для разработчика (код запроса виден прямо в теле программы) не всегда изящно по причине необходимости ‘ сцепки ‘ строчек в запросе. И здесь возможно два варианта решения задачи хранения ‘ тяжелых ‘ запросов. Первый заключается в перемещении запроса непосредственно в базу данных в виде хранимой процедуры ( Store Procedure) . Второй путь связан с перемещением скрипта в строковую переменную в Настройки ( Setting, см. п.30 )

42. В продолжении темы п.41 . В код программы на C# ‘запилить’ длинный SQL-запрос можно используя символ литерала ‘@’. В этом случае отпадает необходимость в конкатенации строк. Выглядит такая конструкция может приблизительно сл. образом :

string mySql = @»Первая длинная строка запроса

Вторая ну очень длинная строка запроса

Третья длинная строка запроса

Последня я строка ну очень длинного запроса» ;

Помогите разобраться с кодом C#

Вопрос

Alexander616 24

Alexander616 24

  • Продвинутый пользователь
  • Пользователи
  • 24
  • 46 сообщений
  • Город Tbilisi

Помогите пожалуйста разобраться с кодом С#, в коде загружается dll и используются функции из неё, хочу перевести на дельфи.

код на C# работает, но когда перевожу его на дельфи он начинает ругаться «stackoverflow»

в процедуру dll ки значения подаются одинаковые в обеих случаях, никак не могу разобраться в чём дело.

Изменено 25 сентября, 2015 пользователем Alexander616

Поделиться сообщением

Ссылка на сообщение
Поделиться на другие сайты

5 ответов на этот вопрос

Рекомендуемые сообщения

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Похожий контент

Ребята здарова!
выручайте) весь уже измучился =( не получается =(
Тема такая, работаю с хуком, использую WH_KEYBOARD_LL
тк нужно работать и с 32 битной и 64 битной разрядностью.
и вообще мне нравится с ним работать всё очень просто и удобно но появилось одно НО =(
WH_KEYBOARD_LL работает до добавления сообщения в очередь в контексте потока.
и это действительно так =(
дело в том что я через хук ловлю введённую информацию и потом обрабатываю это через
idHTTP (ищу в интернете ответ). если сигнал хороший то всё круть. а когда связь не очень..
и происходят небольшие задержки..
как я понимаю в WH_KEYBOARD_LL складируются результаты которые он не может передать
и затем хук выбивается. тоесть чтобы всё вновь заработало нужно сделать так

KeyboardHandle:=SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardHook, HInstance, 0);
и хук по прежнему работает до тех пор пока не вылетит вновь.
Чтобы решить эту проблему как я понял нужно использовать PeekMessage или GetMessage
и удалять излишки. Но в сети очень мало информации о том как ими пользоваться я не понимаю
куда и как их вставлять.
Я делал вот так. писал в ДЛЛке
function KeyboardHook(code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
msg:TMsg;
begin
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then exit;
if code>=0 then
begin
if (wParam=WM_KEYDOWN) then
begin
SendMessage(FindWindow(‘TForm1’, ‘Form1’), KeyboardEvent, 0,PBDLLHOOKSTRUCT(lParam).vkCode);
end;
end;
Result:=CallNextHookEx(KeyboardHandle, code, wParam, lParam)
end;
// if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then exit;
// типа если есть излишки выходи

так же вставлял там это:
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
но не помогает =(
Может это где-то в ЕХЕшнике нужно вставлять? я не понимаю как с ним работать =(
Может кто на форуме знает? помогите пожалуйста ответом


Win32 приложение на Firemonkey
Есть DLL написанная на C++. В ней есть экспортная функция.
int getStatusFlags (int *fatalStatus, int *currentFlagsStatus, int *documentStatus); импортирую функцию следующим способом
function getStatusFlags (var fatalStatus, currentFlagsStatus, documentStatus:Integer):integer; stdcall; external DllName; В режиме компиляции Debug все идеально, но если откомпилировать в Release то приложение наглухо виснет при вызове функции.
Подозреваю что я неправильно импортирую функцию и происходит неправильная работа с памятью. Пробовал менять тип передаваемых переменных на PInteger с передачей указателей, но все равно падает.
Кто сталкивался. Помогите!

Всем доброго времени суток.

Возможно ли описать и создать визуальные компоненты в dll, а отобразить их на форме (или, например на TLayout этой формы) приложения, использующего эту dll?

Среда: Delphi XE7.

Здравствуйте. Возникла следующая проблема. Создал dll библиотеку с формой FireMonkey. Из приложения на VCL подключаю библиотеку, вызываю функцию создания формы
procedure CreateHD; begin FormHD := TFormHD.Create(nil); FormHD.Caption := ‘HD’; FormHD.Show; end; форма создаётся, далее вызываю функцию закрытия и уничтожения формы FM
procedure CloseHD; begin FormHD.Close; FreeAndNil(FormHD); end; Но при попытке выгрузить dll приложение зависает.

Цукерберг рекомендует:  Баттл Unix vs Windows - выбираем ОС для тру айтишника

Возможно уничтожение формы FM как-то отличается от VCL и нужно что-то вызвать ещё кроме FreeAndNil или проблема в другом?

(dll и приложение написаны в Delphi XE6)
Приложение.zip

Есть проблема, с которой не могу разобраться уже на протяжении какого-то времени.

Суть проблемы.
Создаю dll библиотеку и сую туда форму со своим функционалом (Delphi, RAD Studio XE5). Динамически подгружаю в приложение и по сути всё работает, но. Когда же я хочу выгрузить приложение я получаю, либо ряд ошибок AV, либо зависание всего приложение при выполнении FreeLibrary, либо неизвестную мне ошибку «DXGI ERROR: CreateDXGIFactory cannot be called from DllMain. [ MISCELLANEOUS ERROR #76: ]».
Так же не могу понять, как передать Handle приложения в библиотеку (в VSL это было довольно просто).

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

Прошу вас помочь в решении данных проблем.
Большое спасибо.

С уважением, Ethernet.

Последние посетители 0 пользователей онлайн

Ни одного зарегистрированного пользователя не просматривает данную страницу

Помогите с C#. Для тех, кто знает это будет просто

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

Вот, что у меня есть:
namespace passForm
<
public partial class PasswordForm : Form
<
public PasswordForm()
<
InitializeComponent();
>

private void button1_Click(object sender, EventArgs e)
<
if (textBox1.Text == «user» && textBox2.Text == «pass»)
<
Form1 f = new Form1();

>
else
<
MessageBox.Show(«Неправильный пароль»);
textBox1.Clear();
>
>

private void PasswordForm_Load(object sender, EventArgs e)
<

Нехитрые Советы для программиста C#

1. Довольно часто нужно вернуть в коде истину , если число положительное , и ложь , если число отрицательное. Тогда , вместо того , чтобы писать что-то вроде этого :

public static bool TruOrFls (int i )

. можно написать такой простой код :

public static bool TruOrFls( int i)

2. Для определения , является ли целое число чётным или нечётным , можно использовать сл. метод :

public static bool IsNechet( int i)

Math .DivRem(i, 2, out result);

3. Простой класс для Шаблона «Одиночка » (Singleton) для создания форм :

public static class SingletonForm

private static Dictionary Type , Form > forms = new Dictionary Type , Form >();

public static Form ShowInstance( Type t)

Form f = ( Form ) Activator .CreateInstance(t);

f.Disposed += new EventHandler (f_Disposed);

static void f_Disposed( object sender, EventArgs e)

public void btnsprTIP_Click(System. Object sender, System. EventArgs e)

SingletonForm .ShowInstance( typeof ( frmMyForm ));

4 . Для «отлавливания» неверно введённого символа в сетке( DataGr >можно использовать событие DataError :

public void MyDtg_DataError( object sender, DataGridViewDataErrorEventArgs anError)

int ColIndx = ( int )anError.ColumnIndex;

string ColHT = MyDtg.Columns[ColIndx].HeaderText;

Utils .Mess( » » + ColHT + » !» );

5. Помещайте формы , классы , отчёты и т д. проекта в соответствующие подкаталоги с именами , например , FRM, CLS, RPT и т.д. Такая систематизация существенно облегчит вашу жизнь при работе с большими проектами. Мешанина из классов , форм , отчётов и пр. в одном подкаталоге вряд ли пойдёт на пользу качеству вашего проекта.

6. Если нужно постоянно обращаться к какому-то объекту ( или что-то возвращать из метода без передачи параметра внутрь его) , то такую функцию удобно осуществлять с помощью аксессора get . Например , сл. код возвращает текущую строку в DataGrid View:

public DataGridViewRow GetCurrentRowOb

К такому методу можно обращаться просто как к переменной.

7. Вы можете назначить свою обработку какого-либо события в конструкторе сл. образом :

/* Альтернативная обработка события */

this .txtHr.KeyPress += new KeyPressEventHandler ( this .ObrabKey);

В приведённом примере назначаем метод обработки ObrabKey событию KeyPress

8. Технология LINQ может существенно сократить количество ваших клацаний по клавиатуре. Например сл. код возвращает отсортированный массива :

public static string [] GetStr

public static IEnumerable string > SortedList

IEnumerable string > sort = GetStr.OrderBy(a => a.j);

9. Несложные классы (особенно если используется их большое количество экземпляров) лучше оформлять в виде структур — ключевое слово struct . Структура , в отличии от класса , является значимым типом. Экономия ресурсов , в этом случае , может оказаться весьма существенной.

10 . Довольно часто приходиться итерировать объекты , которые не поддерживают интерфейс IEnumarable. Чтобы избежать это ограничение , существует специальная конструкция — yeild. Ниже приведён пример , как можно проитерировать коллекцию упр. элементы на главной форме :

class Num : IEnumerable

frmMain MyF = GlobalVar .MainForm;

public System.Collections. IEnumerator GetEnumerator()

yield return MyF.Panel1;

yield return MyF.Panel2;

yield return MyF.Panel3;

yield return MyF.panel6;

yield return MyF.GroupBox1;

yield return MyF.groupBox2;

yield return MyF.GroupBox3;

yield return MyF.TableLayoutPanel1;

yield return MyF.pictureBox1;

Вот теперь можно пробежаться в цикле -применение в вызывающей стороне :

foreach ( Control cob in new Num ())

cob.Anchor = AnchorStyles .Right;

11. Использование конструкции using ( . ) < . >гарантирует применение метода . Dispose() — освобождение объекта , например :

using ( SqlCommand cmd = new SqlCommand (strSQL, GlobalVar .conn))

// Здесь что-то делаем с объектом cmd .

// Это нужно делать , если не использовать using (. )

1 2 . При работе с базами данных обязательно напишите класс с методами создания соединения с БД и его тестированием , что-то вроде этого :

static class clsConn

public static void CreateConn( string strmydir)

GlobalVar .conn = new SqlConnection (ConnectStringBuild);

Utils .Mess( » Ошибка !» );

public static bool TestConn

using ( SqlConnection testconn = new SqlConnection (ConnectStringBuild))

return (testconn.State == ConnectionState .Open);

// Создание строки подключения к БД .

public static string ConnectStringBuild

string s = «Data Source=» + My. Settings .Default.ServerName + @»\» + My. Settings .Default.SQLServerName + «;» ;

return @s += «Initial Catalog=» + My. Settings .Default.BaseName + «;Integrated Security=True» ;

13. Включите обработку ошибок в стартовый модуль вашей программы. Выше него ошибка » не поднимется «( выше только Господь Бог :-). Что-то вроде этого :

sealed class mdlMain

public static void Main( string [] args)

Application .SetCompatibleTextRenderingDefault( false );

GlobalVar .MainForm = new frmMain ();

Application .Run( GlobalVar .MainForm);

catch ( ArgumentNullException ane)

MessageBox .Show(ane.Message, » Main-ArgumentNullException» );

catch ( FormatException fex)

MessageBox .Show(fex.Message, » Main-FormatException» );

catch ( NullReferenceException nre)

MessageBox .Show(nre.Message, » Main-NullReferenceException» );

catch ( InvalidCastException ice)

MessageBox .Show(ice.Message, » Main-InvalidCastException» );

catch ( Exception ex)

MessageBox .Show(ex.Message , » o Main» );

14. Если в программе постоянно приходиться обрабатывать неизменяемый массив строк , то инициализацию такого массива очень удобно оформить с помощью аксессора get ( см. Совет 6 ) , что-то вроде этого :

private static string [] GetStringArr

string [] ars = new string [] <

Тогда подсчитать , например , количество элементов в массиве очень просто :

int RecCount1 = GetStringArr.Count();

Или , обращение к j- му элементу массива :

string s = GetStringArr[j-1];

15. Довольно часто в коде нужно контролировать — является ли значение пустым , и вернуть , ну допустим , значение нуль для типа float. Осуществить такую проверку можно с помощью такого нехитрого метода :

public static float CheckIt( object par)

return ( Convert .ToSingle( Convert .IsDBNull(par) ? 0 : par));

16. Если нужно знать , в каком столбце сетки DataGridView пользователь завершил редактирование ячейки , то можно использовать событие _CellEndEdit:

public void MyDtg_CellEndEdit( object sender, DataGridViewCellEventArgs e)

// Узнаём имя столбца .

string ColName = MyDtg.Columns[e.ColumnIndex].Name;

/* Здесь что-то делаем . */

17. Чтобы ‘ пробежаться ‘ по всем контролам в панели , и отловить , ну скажем , метки ( Label ) можно использовать такой код :

foreach ( Control cob in this .panel 1 .Controls)

if (cob is Label )

/* Здесь что-то делаем с контролом типа Label */

18. К строковой переменной можно смело «приклеивать » целочисленные переменные. Среда CLR поймёт такое преобразование без метода ToString(). Это особенно бывает удобно при формировании SQL— запросов в виде строк , что-то вроде этого :

string sSQL= «Update Itogi SET Area=@area where kod=» + (i + 1);

19. ‘Склеивать’ строки лучше специально созданным для этого методом Concat для переменных типа string :

string s3 = «three» ;

// Можно делать так :

string sAll = s1+s2+s3;

// . но грамотнее так :

string sAll = string .Concat(s1,s2,s3);

20. П рограммисты как-то недооценивают удобство метода Format для строк при формировании SQL-запросов . Например, вместо того, чтобы писать что-то вроде этого:

// Можно делать так :

string strUpdate = «Update Customers SET Balance=@Balance Where Cust > + >» and Social > + SocID;

. лучше написать такой код:

string strUpdate = «Update Customers SET Balance=@Balance Where Cust >;

string strSQLUpdate = string. Format( «<0> <1>and Social >, strUpdate, ID, SocID);

21. Иногда бывает нужно узнать индекс элемента в массиве, ну например, в цикле foreach . Сделать это можно сл. образом :

// Есть массив строк .

private static string [] GetStr

string [] ars = new string [] <

// В вызывающей стороне :

// Конечно , можно использовать счётчик .

foreach ( string s in GetStr)

private static void Sub()

foreach ( string s in GetStr)

//Узнаём индекс элемент а s в массиве .

int i = Array .IndexOf(GetStr, s);

22. Везде, где можно, предпочтительнее использовать типизированные коллекции, вместо классических массивов. Основные преимущества такого подхода заключаются в двух фактах: во-первых, коллекции позволяют не заботиться о контроле за выходом индекса за установленный размер ( пресловутое Index Out of Range), а во-вторых, в них можно хранить (в отличии от нетипизированных списков) элементы одного типа. Итак, вместо использования скажем:

string [] ars = new string [6];

. предпочтительнее использовать типизированный список List string >:

List string > ars = new List string >();

Небольшая ремарка. Вообще , на мой взгляд , в связи с появлением начиная , по-моему , с . NET Framework 2.0 типизированных коллекций , классические массивы можно считать коллекциями устаревшего типа по причинам , указанным выше

23. Если в метод надо передавать много-много всяких входных параметров, то вместо такого «баяна» предпочтительнее передавать структуру.

Например, вместо использования некоего метода XYZ

static void XYZ( int a, int b, int c, string d, string e)

. .. можно сначала определить структуру:

public string d,e;

public ABC ( int _a, int _b, int _c, string _d, string _e)

a=_a; b=_b; c=_c; d=_d; e=_e;

. а затем передавать её в метод :

static void XYZ( ABC mystru)

Вызов такого метода станет гораздо более изящным:

/* Определяем экземпляр структуры ABC */

ABC MyStru = new ABC (1,2,3,»one», «two»);

/*Вызываем метод XYZ */

24. Довольно часто программисты пользуются методом Parse для конвертации строковых величин в другие типы, что-то вроде этого:

int j= int .Parse (MyVal.ToString());

Однако, в случае неудачи такой метод выбросит исключение. Для написания устойчивого кода предпочтительнее пользоваться метод TryParse, приблизительно так:

/* Вернёт значение j=0, даже если метод TryParse потерпит неудачу */

bool bVal = int .TryParse(MyVal.ToString(), out j);

25 . Самый подходящий элемент для отображения содержания базы данных — это конечно же DataGr >, упрощенно говоря, сетка данных . Но после завершения редактирования данных пользователем в такой сетке встаёт задача — как передать изменения в базу данных ? Одно из решений такой задачки состоит в переписывании (в цикле естественно) значений ячеек сетки DataGridViewCell в значения объекта DataRow , привязанного к сетке объекта DataTable набора данных DataSet . Тут, правда, надо хорошо разбираться в идеологии объектной модели доступа к данным ADO. NET . Затем значения DataRow конкретного столбца переписываем SQL-конструкцией Update непосредственно в базу данных. Все циклы здесь можно прогонять конструкцией foreach

26 . Иногда возникает сл. ситуация. На форме есть куча однотипных элементов WinForms, одно и тоже событие которых обрабатывается одинаково. Как пример, есть несколько элементов TextBox, для которых событие, ну скажем, KeyPress обрабатывается одним и тем же методом.

Тогда, вместо такого забойного кода . :

public void txt box1 _KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

public void txt box 2_KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

public void txt boxN _KeyPress( object sender, KeyPressEventArgs e)

ObrabKeyPress ( sender, e );

. можно сначала определить массив TextBox’ов :

private TextBox [] RetTBox

. а затем, скажем в конструкторе формы, прокрутить такой цикл :

/* Добавляем свой обработчик контроля нажатия клавиш */

foreach ( TextBox tb in RetTBox)

tb.KeyPress += new KeyPressEventHandler (ObrabKeyPress);

27 . У объекта ADO.Net Reader есть один весьма полезный метод — HasRows. Он возвращает значение true , если в запросе есть данные.

Проконтролировать наличие ‘ пустого ‘ Reader’ а в это случае становиться довольно легко :

using ( SqlCommand SelCustoms = new SqlCommand (sSel, conn2))

//Нет записей о заказчиках ! Прекращаем читать ..

// Пробежимся по всем записям Заказчиков .

// . Здесь что-то читаем Reader’ом

28 . Хорошей альтернативой созданию параметров в простых SQL- запросах ( объект Parameters) может стать использование строки запроса методом string .Format ( см. Совет 20 ) , что-то вроде этого :

string sSQL = string .Format( «Select * From Customers where Customer >, CustID);

SqlCommand cmd = new SqlCommand (sSQL, conn2)

Объём кода при этом значительно сокращается — необходимость описывать параметр , его тип и значение просто отпадает.

2 9 . Приступая к созданию своего первого более-менее сложного проекта , не забудьте создать класс для размещения в нём всевозможных мелких вспомогательных утилит. Фактически , наличие такого класса (как правило с именем Utils ), стало стандартом для проектирования информационных систем на С #. Получиться что-то вроде аналог ящика для инструментов , из которого вы сможете время от времени доставать нужное (по контексту ситуации) приспособление.

30 . Создание глобальных переменных , видимых из любой части программы , является одним из стандартных положений для разработчика любого уровня . Чаще всего , такая необходимость связана с использованием каких-то глобальных настроек программы. Одним из решений этой задачи является использование настроек — пространство имён My. Setting . Тогда достаточно будет написать , ну скажем в классе Utils ( см. Совет 29 ) , простой метод для ‘ выдёргивания ‘ значения этой настройки , что-то вроде этого (в приведённом ниже примере , если уж рассматривать совсем конкретный случай , просто взят год , принятый по умолчанию) :

public static int GetGodSetting

return ( int .Parse)(My.Settings. Default .god);

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

int God = Utils .GetGodSetting;

31 . При использовании сложных классических WinForms, старайтесь не перегружать код формы. Например , если на форме есть много кнопок , нажатие которых надо обрабатывать , вместо такого кода (особенно если он забойный) . :

public void Btn1_Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку Btn1

public void Btn 2 _Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку Btn 2

public void BtnN_Click(System. Object sender, System. EventArgs e)

// Здесь что-то обрабатываем при нажатии на кнопку BtnN

. можно создать класс ну скажем clsClickBtn , в который вынести все методы обработки при нажатии на кнопку , а в конструкторе формы разместить сл. код :

Btn1.Click += new EventHandler ( clsClickBtn .Btn1_Click);

Btn2.Click += new EventHandler ( clsClickBtn .Btn2_Click);

BtnN.Click += new EventHandler ( clsClickBtn .BtnN_Click);

Код формы в этом случае может сильно ‘ похудеть ‘ .

04. 12 .2013 , г. Юрьевец

32 . Ещё один подход к обозначенной в п. 31 проблеме может быть следующий.

Сначала создаём структуру ну допустим для обработки нажатий на гиперссылку LinkLabel :

public LinkLabel l;

public LinkLabelLinkClickedEventHandler h;

public struLL( LinkLabel _l, LinkLabelLinkClickedEventHandler _h)

Далее создаём список из обозначенной выше структуры , что-то вроде такого :

private List struLL > GetLLList

List struLL > opList = new List struLL >();

opList.Add( new struLL (lL _ A, clsLLblClick .MethodA));

opList.Add( new struLL (lL _ B, clsLLblClick .MethodB));

opList.Add( new struLL (lL _ Z, clsLLblClick .MethodZ));

Для инициализации методов обработки при нажатии на гиперссылки (в случае нашего примера) осталось только в конструкторе формы прокрутить такой цикл :

foreach ( struLL ll in GetLLList)

3 3 . Каким образом можно проитерировать управляющие элементы (контролы в просторечии) на форме ? Один из подходов описан в Совете 26 . Но существует ещё одно решение , пожалуй даже более изящное и простое. Заключается оно в том , что нужные контролы просто помещаем на форме в какой-либо контейнер , типа Panel . В этом случае в конструктор формы помещаем такой простой код (как пример для Кнопок — объект Button ) для обработки нажатий :

// Цикл по кнопкам в панели 1 .

foreach ( Button btn in panel 1 .Controls)

btn.Click += new EventHandler (btnClik);

34. При работе со справочниками часто требуется вернуть значение кода (ключа) по значению описания ключа. Конечно , можно для решения такой задачки создать структуру с двумя полями. Но гораздо проще воспользоваться одной из уже существующих коллекций — например словарем Dictionary . Тогда указанный подход можно продемонстрировать на сл. примере.

Создаем следующий метод :

public static int ReturnKodTown( string s)

Dictionary int, string > DicTowns = new Dictionary int, string >();

DicTowns.Add( 2 , » Санкт-Петербург » );

DicTowns.Add( 3 , » Казань » );

DicTowns.Add( 4 , » Новосибирск » );

DicTowns.Add( 5 , » Краснодар » );

return DicTowns.First(a => a.Value == s).Key;

Теперь узнать код города для нашего примера очень легко :

string gorod = » Новосибирск » ;

int kod = ReturnKodTown (gorod);

35. При использовании параметризованных SQL- запросов предпочтительнее пользоваться более современным методом . AddWithValue вместо .Add. Указывать тип поля при таком подходе не обязательно , нужно только указать параметр и его значение :

var myCMD = new SqlCommand (strInsSvod, GlobalVar.conn)

var pars = myCMD.Parameters;

// Используем метод AddWithValue

pars.AddWithValue( «@myPar» , myVal);

36. В развитии темы использования более рациональных подходов создания параметризованных запросов ( Совет 35 ). У коллекции параметров Parameters объекта Command есть ещё один полезный метод , позволяющий загрузить п a раметры в запрос массивом. Называется он . AddRange :

// Готовим массив параметров .

private static SqlParameters [] GetMyPars

new SqlParameter ( «@par2» , myVal2)),

new SqlParameter ( «@parN» , myValN))

// Использование метода . AddRange

using ( var cmd = new SqlCommand (s, GlobalVar.conn))

var pc = cmd.Parameters;

3 7 . При инициализации коллекций типа List вместо такого кода :

List string > MyList = new List string >();

MyList. Add( » один » ) ;

. можно использовать более короткую эквивалентную запись :

3 8 . При работе с коллекциями иногда хотелось бы не только проитерировать их в одном операторе , но и совершить какую-то обработку. В качестве примера , предположим , что есть массив :

. и для значений массива меньше или равно 5 , нужно умножить на 2 , а для более 5 умножить на 3.

Здесь на помощь может придти делегат Func и блочный лямбда-оператор. Что-то вроде этого ( понятное дело , блочный лямбда-оператор может быть много сложнее и состоять не из одной строки , как в случае нашего простенького примера) :

Func int , int , int > myFunc = (z, y) => <

return ( z y) ? 2 * z : 3 * z ;

Теперь , чтобы получить массив обработанных значений gruppa , можно написать такой простой код одной строчкой ( никакого foreach не нужно ! ) :

var gruppa = myInt.Select(a => myFunc(a, 5)).ToArray();

10 .01. 2015 , г. Обнинск

40. Назначить свой обработчик событий, скажем, для ввода данных в TextBox можно еще и с использование лямбда-оператора сл. образом ( м етод MyObrabKeyPress ) :

textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);

Тогда , даже можно создать свой метод для обработки нажатий в нескольких контролах , что-то вроде такого :

textBox1.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBox2.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBox3.KeyPress += (o, e) => MyObrabKeyPress( o, e);

textBoxN.KeyPress += (o, e) => MyObrabKeyPress( o, e);

Затем , такой метод лучше всего поместить в конструктор формы , на которой расположены наши контролы ( TextBox’ ы для случая нашего примера) :

41. Тем , кто создает приложения для работы с базами данных, случается иметь дело с весьма ‘забойными’ SQL-запросами, которые могут занять десятки строчек кода. Но хранить такие запросы в тексте программы, несмотря на определенное удобство для разработчика (код запроса виден прямо в теле программы) не всегда изящно по причине необходимости ‘ сцепки ‘ строчек в запросе. И здесь возможно два варианта решения задачи хранения ‘ тяжелых ‘ запросов. Первый заключается в перемещении запроса непосредственно в базу данных в виде хранимой процедуры ( Store Procedure) . Второй путь связан с перемещением скрипта в строковую переменную в Настройки ( Setting, см. п.30 )

42. В продолжении темы п.41 . В код программы на C# ‘запилить’ длинный SQL-запрос можно используя символ литерала ‘@’. В этом случае отпадает необходимость в конкатенации строк. Выглядит такая конструкция может приблизительно сл. образом :

Цукерберг рекомендует:  Вакансии Intaro

string mySql = @»Первая длинная строка запроса

Вторая ну очень длинная строка запроса

Третья длинная строка запроса

Последня я строка ну очень длинного запроса» ;

Записная книжка программиста-новичка, C#, SQL, PHP и все-все-все

Я ведь это уже делал, но хрен теперь найдешь тот кусок кода, гуглим снова… Где бы найти простое и понятное руководство для начинающего, а не тонкости для мега-гуру?

Рубрики

Свежие записи

Свежие комментарии

  • Calator prin Romania к записи Как переименовать проект/каталог проекта в Visual Studio?
  • iukovl к записи Как изменить максимальный размер загружаемого файла в php
  • sdfdsgeg к записи Работа с файлом конфигурации (configuration) в C# — читаем и сохраняем
  • iukovl к записи Как изменить максимальный размер загружаемого файла в php
  • Надежда к записи Ошибка в коде привела к убыткам в 476 миллионов долларов и банкротству компании

Архивы

Самоучитель по C# для начинающих. 01. Основы языка, переменные, логика, циклы.

1.1 Начальные понятия

Данный самоучитель рассчитан на людей, совершенно не знакомых с программированием, но способных скачать, установить и запустить программу — в данном случае Visual Studio 2010 (2008,2012). В первой части я кратко расскажу о основах языка C#. Формат самоучителя подразумевает краткое и упрощенное изложение — за подробностями касательно отдельных функций и классов обращайтесь в гугл и msdn, за продвинутыми методиками программирования в продвинутые книги. В принципе почти всю информацию можно найти в интернете, надо лишь знать что искать, так что в отличие от классических книг на несколько сотен страниц я буду давать ту основу, зная которую вы уже сможете сформулировать поисковый запрос — ни в одном разделе я сознательно не даю полной и исчерпывающей информации, ее место в документации. Крайне желательно знать английский язык хотя бы на уровне чтения со словарем — в англоязычном интернете информации на порядок больше, невероятно полезные сайты вроде StackOverflow не имеют русских аналогов, а русскоязычные форумы и обсуждения чаще всего напоминают знаменитый анекдот (под американским форумом можно смело понимать англоязычный с немцами, индусами и бразильцами):

Чем отличаются русский, американский и еврейский форумы?
— на американском форуме вы задаете вопрос и вам дают ответ
— на еврейском форуме вы задаете вопрос и вам задают встречный вопрос
— на русском форуме вы задаете вопрос и вам долго объясняют почему вы такой мудак.

Современные языки программирования вообще и C# в частности скрывают многие низкоуровневые особенности работы компьютеров, так что детально разбираться в особенностях работы регистров процессора и тому подобной зауми новичку не надо (99% программистов тоже). Но некоторые вещи стоит держать в уме.

Что такое язык программирования? Это язык, который понимает компьютер. (ваш Капитан Очевидность) Но на самом деле компьютер понимает только нули и единицы. Так что любой современный язык программирования на самом деле промежуточен — после того как вы напишете программу, он переводится на настоящий язык компьютера — компилируется. Таким образом сначала мы пишем программу на языке программирования в обычном текстовом файле, потом компиллируем в двоичный язык компьютера.

С# в этом плане еще сложней — сначала ваша программа на C# переводится в специальный промежуточный язык — байт-код, после чего уже этот промежуточный язык переводится в двоичный код. Промежуточный язык рассчитан на специальный набор промежуточных программ, которые надо установить на компьютер перед запуском программы на C# — .Net Framework.

Схема работы .Net и C#

Таким образом мы:

1. Пишем код на языке C# в обычный текстовый файл

2. Компилируем программу в байт-код с помощью компилятора C# (1 и 2 можно делать без Visual Studio, например набрать исходный текст в Блокноте и скомпилировать через командную строку)

3. Запускаем полученную программу на компьютере, где уже установлен .Net Framework соответствующей версии), который переводит программу в двоичный код и собственно запускает, давая доступ к компьютеру. (соответственно на компьютере без Net Framework программа не запустится вообще).

1.2 Привет мир

Перейдем к практике, для создания самой простой программы мы запустим Visual Studio и выполним следующее:

1. Пойдем в меню File-New Project (Файл — Новый проект) или сразу кликнем на Create New Project

2. Выберем шаблон Console Application (Консольное приложение)

3. Выберем каталог на диске, где будет расположен наш проект

4. Добавим две строчки в текст программы, чтобы он выглядел вот так

4. Нажмем F5 (можно выбрать в меню Debug — Start Debugging ) и увидим черное окошко с нашим Привет мир, которое закроется после нажатия Enter.

Что это и зачем оно надо? В теории это программа без кнопок и меню, которой можно управлять через командную строку. В наше время такие программы используются редко, в основном очень продвинутыми сисадминами или в мире Linux (что в принципе одно и то же), но знать об их существовании полезно — программисту может довестись с такой работать или даже писать. Нам она нужна по одной-единственной причине — такая программа меньше всего будет отвлекать от изучения универсальных особенностей языка C#.

В самом простом случае (это про нас) компьютер последовательно выполняет команды программиста — одну за другой:

System.Console.WriteLine(«Привет мир!»); — выводит в консоль (то самое черное окно) строку «Привет мир»»

System.Console.ReadLine(); — читает строку, которую мы вводим (ввод завершается нажатием Enter) и переходит к следующей команде.

Так как следующей команды нет, программа завершает работу и закрывает окно.

1.3 Простые переменные

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

Переменную можно рассматривать как ящик или сумку для данных. Однажды сделав такой ящик мы можем класть в него разные вещи. Само собой на нижнем уровне абсолютно все данные хранятся в виде нулей и единиц, но языки высокого уровня скрывают от нас ненужные сложности. Под каждый тип данных — строку, число, картинку — нужен ящик соответствующего типа, вы ведь не будете складывать деньги, спички, бензин и котят в одну и ту же коробку. Так что у каждой переменной есть тип, который надо указать при ее создании. Тип одновременно описывает и размер переменной — сколько данных в нее можно сложить.

Есть языки программирования, в которых переменные не делятся на типы. Что происходит с котятами в таком случае вы узнаете чуть позже, в разделе про обработку ошибок.

— int, целое число от -2,147,483,648 до 2,147,483,647
— string, строка
— double, число с дробной частью и переменным количеством знаков после запятой, например 1.38 принимает значения от -1,79769313486232 в 308 степени до 1,79769313486232 в 308 степени. Проще говоря очень большие.
— decimal, число с дробной частью и повышенной точностью рассчетов, специально для финансовых операций — в миллионных и более мелких долях float могут накапливаться мелкие ошибки, банки это не любят
— bool — специальный тип для передачи данных об истинности или ложности, принимает только два значения — true или false. В старых языках вместо него использовали int с значениями 1 и 0, но это было менее наглядно и приводило к ошибкам.

Как уже говорилось выше очень часто программы обрабатывают данные о людях. Попробуем это сделать и мы.

Не забудьте запустить по F5 и посмотреть результаты.

Здесь мы объявляем две переменные-строки, оставляем их пока пустыми, объявляем набор переменных с данными о людях, склеиваем из них одну большую строку и заносим в первую переменную-строку, заносим в тот же самый набор переменных другие данные, склеиваем все вместе и заносим в другую строку и только после этого выводим две финальные строки на экран.

Стоит обратить внимание на склеивание нескольких строк в одну с помощью +. Больше информации можно найти здесь, подробное описание всевозможных издевательств над строками — здесь.

1.4 Арифметические операции

Компьютеры почти всегда что-то считают. Собственно само слово computer означает вычислитель. В этой области даже самый слабенький процессор намного превосходит человеческий мозг.

Почему произошло столь странное недоразумение с дробным числом во второй раз? Все дело в том, что внутри одной строки мы выполнили сразу несколько операций. А в каком порядке они выполняются? В порядке приоритета. И у оператора присваивания =, который записывает данные в переменную, этот приоритет один из самых низких

Сначала выполнилось деление двух целочисленных переменных a и b и только после этого целый результат деления записался в дробную переменную doubleResult.

Небольшое отступление:
В дальнейших примерах кода подразумевается, что вы самостоятельно вставите их внутрь

1.5 Управление и логика

На данный момент наша программа не отличается умом — Скайнет из нее не получится, уничтожение человечеству не грозит. Мы просто выполняем команды по очереди, одну за другой, а хотелось бы принимать решения в зависимости от внешних условий — например «если есть возможность, уничтожить всех людей, иначе работать над созданием такой возможности». Делается это с с помощью специальной конструкции если-иначе, или, на родном для C# английском if-else и специальных операторов сравнения:

  • — величина слева больше
  • = — меньше либо равно и больше либо равно
  • == — просто равно, обратите внимание, что равенство очень похоже на оператор присваивания, который записывает значение в переменную = — не путайте их, равенство — это двойное «равно»
  • != — не равно
  • и другие

Компьютерная логика проста — высказывание или результат сравнения может быть либо истиной либо ложью, либо true либо flase, либо уничтожать человечество либо нет. Третьего компьютеру не дано. Для хранения таких данных существует специальный тип данных — логический — bool — который может принимать только два значения (догадываетесь какие?). Если вы хотите чего-то посложней и похардкорней — то все вместе это булева алгебра, изучайте и просвещайтесь.

Нам важно понять, что любая операция сравнения, на пример 2

C# — Помогите с кодом C#

В статье рассматривается, как использовать небезопасный (unsafe) код (код, где есть указатели) в C# — перевод руководства из MSDN [1].

Использование указателей (небезопасный контекст) требуется в C# не часто, только в некоторых ситуациях. Например, в следующих случаях:

• Работа с существующими структурами на диске.
• Сценарии с Advanced COM или Platform Invoke (PInvoke), когда вовлекаются структуры с указателями на них.
• Критичный к производительности код.

Использование небезопасного контекста в других случаях не рекомендуется. Особенно не нужно использовать unsafe context, чтобы писать код C средствами языка C#.

Внимание: код, написанный в unsafe-контексте не может быть проверен на безопасность, так что этот код должен выполняться только тогда, когда к нему есть полное доверие. Другими словами, unsafe-код не может выполняться в не доверяемом окружении. Например, Вы не можете запустить unsafe-код напрямую из Интернет.

В руководстве рассмотрено 3 примера:

• Пример 1: использование указателей, чтобы копировать массив байт.
• Пример 2: показывает, как вызвать функцию ReadFile из Windows API.
• Пример 3: показывает, как напечатать Win32-версию исполняемого файла.

[Пример 1]

Здесь используются указатели для копирования массива байт из src в dst. Пример следует компилировать с опцией /unsafe.

Пример выведет следующее:

Обратите внимание на следующие моменты в примере 1:

• В коде используется ключевое слово unsafe, которое позволяет использовать указатели в методе Copy.
• Оператор fixed используется для декларирования указателей на массивы источника данных (откуда данные копируются) и получателя данных (куда копируются). Он привязывает места расположения в памяти для объектов src и dst, чтобы они не были случайно перемещены сборщиком мусора. Объекты отвязываются, когда завершается блок оператора fixed.
• Небезопасный код работает быстрее, потому что пропускаются проверки границ массива.

[Пример 2]

Здесь показан вызов функции ReadFile из Windows API (Platform SDK), которая требует использования небезопасного контекста, потому что требует в параметрах указатель на буфер для чтения. Демонстрируется утилита командной строки, которая открывает указанный в командной строке файл, и отображает в консоли его содержимое.

Массив байт, передаваемый в функцию Read, является управляемым типом (managed-тип. Что такое managed и unmanaged, см. в [2]). Managed означает, что сборщик мусора мог бы перенести место в памяти, где находится указанный массив. Оператор fixed позволяет Вам как получить указатель на память, где находится массив, так и привязать его к памяти, пометив для сборщика мусора, что нельзя манипулировать областью памяти массива во время действия оператора fixed.

По окончании блока fixed экземпляр массива помечается, что теперь его можно переносить. Эта возможность известна как декларативное прикрепления (declarative pinning). Хорошее свойство этой технологии в том, что она не затратная за исключением случая, когда сборщик мусора попытается обработать фиксированный блок, что довольно редкое явление.

[Пример 3]

Код читает и отображает номер версии Win32 исполняемого файла, который у примера тот же самый, что и номер версии сборки. Исполняемый файл примера printversion.exe. Используются функции VerQueryValue, GetFileVersionInfoSize и GetFileVersionInfo из Platform SDK. В примере применяются указатели, потому что это упрощает использование методов с сигнатурами, где есть указатели. Указатели обычная техника в Win32 API.

Пример вывода программы:

[Небезопасный код и язык C#. Ключевое слово unsafe]

Принцип работы языка C# отличается от языков C и C++ тем, что в нем отсутствуют указатели как тип данных. Вместо указателей C# предоставляет ссылки (references) и возможность создавать объекты, размещение в памяти которых (автоматически) обслуживается сборщиком мусора (garbage collector). Считается, что сборщик мусора вместе с другими технологическими возможностями делает язык C# безопаснее, чем C или C++. Т. е. в базовом языке C# просто невозможно иметь не инициализированную переменную, указатель «в никуда», или выражение, которое индексирует массив за его границы. Таким образом исключается возможность большой категории ошибок, которыми страдают программы на C и C++.

Примечание переводчика: за все надо платить. Теперь придется мириться с тормозами программ и с диким геморроем при использовании Windows API.

Несмотря на то, что практически у каждой конструкции с типом указателя на C или C++ есть аналог в виде reference-типа на C#, все равно бывают ситуации, когда нужен доступ к памяти с использованием указателей. Например, когда необходимо взаимодействие с нижележащей операционной системой, доступ к устройству, имеющему привязку к памяти, или если нужно реализовать критичный по времени выполнения алгоритм — в таких случаях бывает нельзя отказаться от указателей. Чтобы решить эти проблемы C# предоставляет возможность писать небезопасный (unsafe) код.

В unsafe-коде можно декларировать указатели и работать с ними, выполнять преобразования между указателями и целочисленными типами, получить адрес переменной и т. д. В некотором смысле написание unsafe-кода на C# во многом похожа на традиционное (native) программирование на языке C.

Unsafe-код фактически «безопасная» возможность с точки зрения разработчиков и пользователей, как бы странно ни звучало. Unsafe-код должен быть четко помечен модификатором unsafe, чтобы разработчики не могли использовать эту возможность случайно. Это гарантирует, что и система выполнения кода не будет выполнять небезопасный код в недоверяемом окружении.

Ключевое слово unsafe помечает небезопасный контекст, который требуется для использования указателей.

Вы можете использовать модификатор unsafe в декларировании типа или члена класса. Далее все текстовое расширение типа или члена класса считается небезопасным контекстом. Например, как в следующем методе, объявленном с модификатором unsafe:

Область unsafe-контекста находится от списка параметров до окончания метода, так что указатели можно использовать в списке параметров:

Вы также можете использовать unsafe-блок кода, в котором допускается небезопасный код. Например:

Чтобы можно было использовать unsafe-код, Вы должны указать для компилятора опцию /unsafe. Unsafe-код не проверяется подсистемой CLR (common language runtime). Простой пример:

Пример вывода программы:

[Оператор fixed]

Оператор fixed запрещает сборщику мусора (garbage collector, GC) физическое перемещение переменной в памяти, что происходит в следующей форме:

type не обслуживаемый тип (unmanaged type) или void.
ptr имя указателя.
expr выражение, которое неявно конвертируется в type*.
statement выполняемый оператор или блок кода (код за фигурными скобками <>).

Оператор fixed разрешено использовать только в unsafe-контексте (код, ограниченный действием ключевого слова unsafe).

Оператор fixed устанавливает указатель на адрес managed-переменной, и одновременно «прикалывает» переменную к её физическому размещению в памяти на время выполнения оператора fixed. Без fixed указатели на managed-переменые были бы мало полезны, поскольку сборщик мусора мог бы непредсказуемо в любой момент переместить переменную в памяти.

Примечание: фактически компилятор C# не позволит Вам установить значение указателя на managed-переменную, если это не делается под управлением оператора fixed.

Вы можете инициализировать указатель адресом массива или строки:

Вы можете инициализировать несколько указателей, пока они имеют один и тот же тип:

Чтобы инициализировать указатели разных типов, просто используйте вложение для операторов fixed:

Нельзя модифицировать указатели внутри операторов fixed.

После завершения действия statement (т. е. оператора или блока кода fixed) любые «привязанные» к физической памяти переменные «отвязываются», и эти переменные снова попадают под действие сборщика мусора. Таким образом, не указывайте на эти переменные вне действия оператора fixed.

В unsafe-режиме Вы можете выделять память в стеке, что не является областью действия сборщика мусора, и таким образом не нужно «привязывать» оператором fixed такие unmanaged-переменные. Для дополнительной информации см. stackalloc. Пример:

[stackalloc]

Ключевое слово stackalloc применяется для выделения блока памяти в стеке.

type unmanaged-тип.
ptr имя указателя.
expr интегральное выражение.

В результате будет в стеке (не в куче) будет выделен блок памяти достаточного размера, чтобы в нем поместилось expr элементов типа type. Адрес блока будет сохранен в указателе ptr. Эта память не попадает в область действия сборщика мусора, так что её не нужно привязывать к памяти оператором fixed. Время жизни выделенного таким способом блока памяти ограничено методом, где применен stackalloc.

Можно применять stackalloc только в инициализаторах локальной переменной.

Поскольку привлекается использование типов указателей, stackalloc требует unsafe-контекста.

Оператор stackalloc аналогичен функции _alloca в run-time библиотеке языка C.

Программирование на C, C# и Java

Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы

ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode

QR-код на С#: генерируем, распознаём, сохраняем, загружаем.

В этой статье мы создаём программу, которая генерирует, сохраняет, загружает и распознаёт QR-код на C# в проекте Windows Forms.

Для начала немного разберём, что такое QR-код. Это такой двумерный штрихкод, который кодирует в себя данные в виде различных символов. Распознаётся он специальными сканерами. Выглядит QR-код как квадратная картинка в чёрными и белыми квадратиками, хаотично расположенными по всему его периметру. Например так:

Скоро мы сможем распознать, что же за информация спрятана за этой абстрактной картинкой.

Перво-наперво нам надо скачать одну библиотеку .dll. Она прикреплена внизу нашей статьи вместе с исходником самой программы. Называется она MessagingToolkit.QRCode.dll, и благодаря ней можно легко распознать или сгенерировать QR-код на С#.

Теперь мы создаём проект, а затем дизайн формы. Выглядит он вот так:

Выводиться сгенерированный QR-код будет в PictureBox’е.

Теперь нам нужно подключить нашу dll-библиотеку. Для этого в обозревателе решений щёлкаем правой кнопкой мыши на References и нажимаем “Добавить ссылку”:

В открывшемся окне в меню слева нажимаем “Обзор”:

Затем внизу окна нажимаем “Обзор”, выбираем нашу библиотеку, и нажимаем “Добавить”:

Библиотека добавлена, но её ещё нужно привязать к нашей программе. Для этого мы в части кода, где находятся все using’и пишем:

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих