уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Хотел было сразу начать выкладывать готовые листинги с кодом программы и комментировать их, но в последний момент решил остановиться на тех особенностях .NET с которыми, впервые столкнувшись, можно несколько “потеряться” после долгой работы, например, в Delphi for Win32. Ну, а так как серия этих статей рассчитана в первую очередь на то, чтобы научиться писать программы под .NET, то некоторые выкладки по теории лишними явно не будут.

Начать, думаю, стоит с ответа на вопрос “Какой язык лучше использовать при работе с .NET?”. Бесспорно, что любой человек, кто хотя бы краем уха слышал о .NET ответит на этот вопрос примерно так – “C#!!” :) А почему? Есть же и Delphi Prism и другие языки, рассчитанные под работу с .NET. И вот на этом моменте мы и остановимся вначале.

Выбор языка программирования

Как-то в одном блоге, посвященном работе с .NET прочитал довольно интересную мысль: “В .NET все языки равны, но некоторые — ровнее”. По-моему абсолютно точный ответ на вопрос – “почему С#?”. C# просто оказался ровнее всех других. Ведь, если посмотреть на описание .NET Framework на MSDN можно увидеть целый перечень того, какие преимущества дает нам эта технология, в том числе и среду CLR, которая, цитирую:

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

На каком бы языке ни писалась программа – мы в любом случае будем работать:

  1. со средой CLR
  2. с одними и теми же классами из .NET Framework

Поэтому выбор C# ИМХО обуславливается только следующими объективными причинами:

  1. Цена – скачайте Visual Studio Express для работы с C# и работайте бесплатно. Да и в принципе стоимость студии как таковой ниже, чем той же RAD Studio. И, по-моему это самый мощный и веский аргумент в пользу C#.
  2. Наследие языка – здесь я имею в виду то, что C# разрабатывался изначально под .NET и, хоть синтаксис и был наследован по большей части из C и C++ С# тем не менее, в отличие от других языков, C# изначально не требовалось тянуть за собой воз устаревшего и небезопасного кода лишь для сохранения совместимости. Поэтому можно считать, что C# более …безопасен и компактен что ли, по сравнению с другими.

Остальные причины, почему вдруг надо все бросить и бежать учить C# ИМХО чисто субъективный взгляд на программирование, либо неприкрытый маркетинговый ход, либо такой же не прикрытый троллинг. Например, выражения типа “На C# писать быстро и удобно” не выдерживает никакой критики с точки зрения выбора языка, например, мной. Мало ли, что вместо begin…end используются фигурные скобки? Может у меня скорость печати такая, что я десять раз смогу написать begin пока другой тянет палец к кнопке на клавиатуре? Может у меня рефлекс выработан на таком уровне, что я даже не задумываясь пишу эти 8 символов. “Удобно” – чисто субъективное мнение. Можно приспособиться к чему угодно и считать это удобным – будь то смена места жительства, смена рациона питания или выбор языка. Одному удобно летать в Тайланд из Краснодара, а другого прёт от поездки на поезде до Москвы, а оттуда летать самолетом — удобно ему. Мне, например, удобно сначала писать имя переменной, а потом её тип, а не наоборот. Удобно и всё тут! И хоть убейтесь, доказывая обратное – понятие “удобство” можно применить к одному человеку, к группе, но никак не ко всем и сразу.

То, что сказано выше, не стоит относить на счет фразы типа “Да C# конченное УГ – все валите в Delphi Prism”. Ни в коем случае. Просто этим я хотел сказать, что реально за C#  после многих лет работы в Delphi стоит браться, если нет финансов на покупку Delphi Prism, а .NET необходим в силу каких-либо причин. В остальном без разницы на чем писать. Можно изучить работу в C#, скажем, для подстраховки, или если на новом месте работу ну никак без C# не обойтись.

Другое дело, если выбор языка стоит перед человеком, который не имеет большого опыта работы ни с одним языком, скажем, проходил когда-то, где-то курс по Delphi, но основ ООП так и не постиг, а тут услышал про .NET и хочет научиться программировать. Почему бы ему не посоветовать C#? Не вижу никаких особых причин ратовать за Delphi Prism или другой язык программирования.

Работа с классами и объектами в .NET

Раз уж мы пишем свое первое приложение, то рассмотрим работу с классами и объектами на примере нашего приложения.

Итак, как говорилось в предыдущем посте, наша программа будет работать с анкетой – показывать пользователю вопрос, получать ответ и складывать полученные баллы. Например, вопрос и ответы могут выглядеть следующим образом:

Вопрос: Рассматриваются ли при предварительной оценке деятельности:

  • инвентаризационные перечни всех видов выбросов, сбросов, отходов;
  • воздействие на окружающую среду;
  • список соответствующих законодательных и нормативных актов / инструкций;
  • оценка существующей практики экологического менеджмента;
  • выполнение рекомендаций, сделанных в ходе предыдущих аудитов / оценок / проверок или в ходе расследования причин и последствий аварийных ситуаций?

 

Варианты ответа:

  • Нет / неизвестно (0 баллов)
  • Один или два пункта присутствуют (5 баллов)
  • Три или четыре пункта присутствуют (10 баллов)
  • Все пункты присутствуют (20 баллов)

 

При этом количество пунктов в вопросе может быть различным – от 0 до бесконечности. Количество вариантов ответа также может быть различно, а за каждый вариант ответа может выставляться различное количество баллов. Отмеченным может быть только один вариант ответа.

Начнем с описания одного варианта ответа. В качестве примера напишем свой класс, содержащий необходимые поля. Для этого запускаем Visual Studio, открываем ранее созданный проект, переходим в обозреватель решений, жмем правую кнопку мыши над названием проекта и выбираем в меню “Добавить –> Создать элемент”:

new_element

В открывшемся окне выбираем “Class” и задаем название класса, пусть это будет TestAnswer.pas, жмем “Добавить”:

new_element_2

В проект добавиться новый файл, содержащий заготовку для нашего класса TestAnswer. Вот это одно из правил к которым придётся немного привыкнуть – каждому классу свой отдельный файл. Нет, никто Вам не запрещает взять и, например, в этом же файле определить ещё 100 других классов, но раз уж используем .NET, то стоит придерживаться тех правил, которые существуют.

Теперь, что касается непосредственной работы с объектами. Как я уже сказал выше, так или иначе в большинстве случаев мы будем работать с CLR. Бесспорным преимуществом среды CLR можно назвать следующее:

Среда выполнения обеспечивает автоматическое размещение объектов и управление ссылками на них, а также освобождение объектов, когда они больше не используются. Объекты, время жизни которых управляется подобным образом, называются управляемыми данными. Сборка мусора исключает утечку памяти и некоторые другие часто возникающие ошибки программирования.”

То есть для нас отпадает необходимость следить за тем, чтобы объект вовремя и, главное, правильно уничтожался – эти рутинные операции берет на себя CLR.

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

namespace gap;
 
interface
 
uses
  System.Collections.Generic,
  System.Text;
 
type
  TestAnswer = public class
  private
  protected
  public
  end;
 
implementation
 
end.

 

То есть в пространстве имен gap создан открытый (public) класс TestAnswer, для которого нам предлагается определить поля и свойства с различной степенью видимости (private, protected, public). Для нашего случая класс ответа должен содержать следующие свойства: текст ответа, балл, который присваивается за этот ответ и последнее свойство — признак того, что ответ выбран. Что касается описания полей и свойств класса, то здесь мы можем смело опираться на тот опыт, который получили при работе с Delphi, например, мы можем определить свойства так:

type
  TestAnswer = public class
  private
     fAnswer: String;
     fBall: Integer;
     fSelected: Boolean;
  protected
  public
     property Answer: String read fAnswer write fAnswer;
     property Ball: Integer read fBall write fBall;
     property Selected: Boolean read fSelected write fSelected;
  end;

А можем дополнительно контролировать процесс присвоения балла за ответ, не допуская, чтобы значение балла было меньше нуля:

type
  TestAnswer = public class
  private
     {...}
     fBall: Integer;
     method SetBall(newBall: integer);
  protected
  public
     {...}
     property Ball: Integer read fBall write SetBall;
     {...}
  end;
 
implementation
 
method TestAnswer.SetBall(newBall: integer);
begin
    if newBall<0 then Exit;
    fBall:=newBall;
end;
 
end.

 

Другой момент — создание объекта. Для примера, создадим новый объект для ответа и присвоим ему первоначальные значения. Для этого воспользуемся уже имеющемся в нашем распоряжении методом-конструктором для MainForm. Для того, чтобы создать новый объект и присвоить ему первоначальные значение напишем в конструкторе следующее:

constructor MainForm;
begin
  InitializeComponent();
  var TestAnsw:=new TestAnswer;
  TestAnsw.Answer:='Ответ';
  TestAnsw.Ball:=123;
  MessageBox.Show(TestAnsw.Ball.ToString);
end;

 

Как видите здесь сразу несколько отличий от того кода, который мы привыкли встречать в Delphi.

Во-первых, мы объявили переменную TestAnsw непосредственно в теле метода.

Во-вторых, объявив переменную мы тут же её инициализировали – TestAnsw уже не будет иметь значение nil. Мы не писали свой конструктор поэтому при создании объекта использовался конструктор по умолчанию. Далее, мы обычным образом присвоили новые значения свойствам Answer и Ball. А вот последняя строка должна вызвать небольшое удивление – мы вызвали метод ToString для свойства тип которого Integer. Это получается, что всё, с чем мы имеем дело в .NET – это объекты? Отчасти это так. Например, подведите и задержите курсор мыши над Integer – вы увидите такую подсказку:

system_int32

Оказывается мы использовали открытый класс причем наследник от кучи интерфейсов. На самом деле в .NET есть всего пять категорий типов:

  • классы;
  • структуры;
  • перечисления;
  • интерфейсы,
  • делегаты;

 

В библиотеке классов .NET Framework все типы-примитивы (Boolean, Byte, Char, DateTime, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32 и UInt64) определяются как структуры. В отношении того же Integer действует механизм автоупаковки, т.е., если попробовать объяснить такую работу кратко, то это означает, что когда нам необходимо просто сложить два числа, скажем 2+2, то система воспринимает эти числа как простые типы данных, но если нам необходим какой-либо метод, скажем ToString, то система автоматически упаковывает значение в объект и отдаст нам список его методов. Необычно по сравнению с тем, что мы знаем из Delphi, но, думаю, что Вы согласитесь, что такой подход имеет свои преимущества и удобство.

Теперь вернемся снова к нашему классу. Что, если нам необходимо при создании объекта передавать ему начальные значения свойств? Дефолтный конструктор уже не поможет. Поэтому здесь нам поможет создание собственного конструктора. Правило создание собственного конструктора следующее – конструктор должен быть безымянным. При этом класс может иметь любое количество конструкторов. Для примера я создал два конструктора для класса TestAnswer:

type
  TestAnswer = public class
  private
     fAnswer: String;
     fBall: Integer;
     fSelected: Boolean;
     method SetBall(newBall: integer);
  protected
  public
     constructor;  
     constructor (aAnswer: String; aBall: Integer); 
     property Answer: String read fAnswer write fAnswer;
     property Ball: Integer read fBall write SetBall;
     property Selected: Boolean read fSelected write fSelected;
  end;
 
implementation
 
constructor TestAnswer;
begin
    fAnswer:='неопределенный ответ';
    fBall:=100;
end;
 
constructor TestAnswer(aAnswer: String; aBall: Integer);
begin
    fAnswer:=aAnswer;
    fBall:=aBall;
end;
 
end.

 

Как видите, в описании класс оба конструктора — безымянны, однако описании конструкторов им присвоено имя в точности совпадающее с названием класса. Это обстоятельство позволяет нам без проблем воспользоваться одним из двух конструкторов практически одинаково:

var TestAnsw:=new TestAnswer;//сработал первый определенный конструктор
var TestAnsw2:=new TestAnswer('Мой вариант ответа',140);//второй конструктор

 

Надеюсь, что теперь при работе с классами в Delphi Prism проблем не возникнет, равно как и при работе с типами данных. Такие вот небольшие, но важные особенности .NET. Теперь можно аналогично представленному выше способу определить собственные классы, например для вопроса теста и попытаться определить в классе методы для отметки определнного варианта ответа и получения текущего балла за ответ на вопрос. Этим мы займемся в следующий раз, а заодно и познакомимся с тем как в .NET осуществляется работа с коллекциями.

0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
2 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
РУДИМЕНТ
РУДИМЕНТ
13/06/2011 06:06

Давно хотел почитать про Prism, спасибо за статью.
Хотелось бы еще почитать как создавать приложения для Linux, а то что-то не удалось разобраться ((

kim-g
kim-g
19/01/2012 12:51

Большое спасибо. Замечательная статья Давно искал подобную статью про переход от Delphi к Delphi Prism.