104
“.NET програмчлалхичээлийн лекцийн хураангуй 1Боловсруулсан багш ММЗТэнхимийн ахлах багш, магистр Б.Болормаа Лекц 1. Сэдэв: .NET Framework ба C# хэл Дэд сэдвүүд 1.1. .NET Платформ 1.2. .NET Фрэймворк 1.3. Хөрвүүлэлт ба MSIL 1.4. C# хэл 1.5. Класс, Объект, Төрөл 1.6. Програмаа хөрвүүлэх, ажиллуулах 1.1 .NET Платформ 2000 оны 7 сард Microsoft .NET платформыг албан ёсоор зарласан байна үүнтэй хамт C# хэл зарлагдсан юм. .NET платформ нь 1990‐ээд оноос хойших Microsoftн гаргасан олон технологиудыг нэг дор авчирсан, шинэлэг програмчлалын интерфэйсүүдээр тоноглогдсон шинэ хөгжүүлэлтийн орчин болсон юм. Үүнд COM+ сервисүүд, ASP вэб хөгжүүлэлт, XML болон объект хандлагат дизайн, мөн SOAP, WSDL, UDDI зэрэг шинэ вэб үйлчилгээний протоколуудыг дурдаж болно. Платформ нь 4 тусдаа бүтээгдэхүүний бүлгээс тогтддог. Үүнд: Хөгжүүлэлтийн орчин: C#, J#, Visual Basic.NET зэрэг хэлүүд; Хөгжүүлэх хэрэгсэл: Visual Studio.NET; Веб үйлчилгээ, виндоуз орчны програмууд хийхэд зориулагдсан баялаг классын сан; Объектуудыг ажиллуулах Common Language Runtime (CLR). Эдгээр нь бүхэлдээ платформын томоохон хэсэг юм. Веб үйлчилгээ: Худалдааны вэб үйлчилгээнүүдийг хөгжүүлэх боломж олгоно, мөн програм бүтээхэд нэг хэсэг нь болон ашиглагдаж болно Тусгай серверүүд: B2B худалдаа (BusinessToBusiness) худалдаа, и‐мэйл, өгөгдлийн менежмент зэрэгт тусгайлан зориулагдсан BizTalk, Exchange, SQL Server зэрэг сервер системүүд Төхөөрөмж: .NET нь үүрэн утаснаас эхлээд тоглоомын төхөөрөмжүүд хүртэлх PC‐бус төхөөрөмжүүд дээр ажиллаж чадна 1.2 .NET Фрэймворк .NET фрэймворк нь үйлдлийн системийн дээд талд ажиллах ба үйлдлийн систем нь Windows ангиллын ямар ч үйлдлийн систем байж болно. Мөн .NET систем нь онолын хувьд өөр үйлдлийн системүүд дээр ажиллах боломжтой,

Dotnet lekts

Embed Size (px)

Citation preview

Page 1: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐1‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц 1.  Сэдэв:  .NET Framework ба C# хэл 

Дэд сэдвүүд 1.1. .NET Платформ 1.2. .NET Фрэймворк 1.3. Хөрвүүлэлт ба MSIL 1.4. C# хэл 1.5. Класс, Объект, Төрөл 1.6. Програмаа хөрвүүлэх, ажиллуулах 

1.1 .NET Платформ    2000 оны 7 сард Microsoft  .NET платформыг албан ёсоор зарласан байна үүнтэй хамт C# хэл зарлагдсан юм. .NET платформ нь 1990‐ээд оноос хойших Microsoft‐н  гаргасан  олон  технологиудыг  нэг  дор  авчирсан,  шинэлэг  програмчлалын интерфэйсүүдээр  тоноглогдсон  шинэ  хөгжүүлэлтийн  орчин  болсон юм.  Үүнд COM+ сервисүүд, ASP вэб хөгжүүлэлт, XML болон объект хандлагат дизайн, мөн SOAP,  WSDL,  UDDI  зэрэг  шинэ  вэб  үйлчилгээний  протоколуудыг  дурдаж болно.    Платформ нь 4 тусдаа бүтээгдэхүүний бүлгээс тогтддог. Үүнд: 

• Хөгжүүлэлтийн орчин:  C#,  J#,  Visual  Basic.NET  зэрэг  хэлүүд;  Хөгжүүлэх хэрэгсэл: Visual  Studio.NET;  Веб  үйлчилгээ,  виндоуз  орчны  програмууд хийхэд  зориулагдсан  баялаг  классын  сан;  Объектуудыг  ажиллуулах Common  Language  Runtime  (CLR).  Эдгээр  нь  бүхэлдээ  платформын томоохон хэсэг юм. 

• Веб  үйлчилгээ:  Худалдааны  вэб  үйлчилгээнүүдийг  хөгжүүлэх  боломж олгоно, мөн програм бүтээхэд нэг хэсэг нь болон ашиглагдаж болно 

• Тусгай серверүүд: B2B худалдаа (Business‐To‐Business) худалдаа, и‐мэйл, өгөгдлийн  менежмент  зэрэгт  тусгайлан  зориулагдсан  BizTalk,  Exchange, SQL Server  зэрэг сервер системүүд 

• Төхөөрөмж: .NET  нь  үүрэн  утаснаас  эхлээд  тоглоомын  төхөөрөмжүүд хүртэлх PC‐бус төхөөрөмжүүд дээр ажиллаж чадна 

 

1.2 .NET Фрэймворк

.NET  фрэймворк  нь  үйлдлийн  системийн  дээд  талд  ажиллах  ба  үйлдлийн систем нь Windows ангиллын ямар ч үйлдлийн систем байж болно. Мөн  .NET систем  нь  онолын  хувьд  өөр  үйлдлийн  системүүд  дээр  ажиллах  боломжтой, 

Page 2: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐2‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

тухайлбал  Linux,  MAC,  Solaris    зэрэг.  Энэ  чиглэлээр  MONO  нэртэй  төсөл амжилттай хийгдэж байна. Вэб хаяг нь http://www.mono‐project.com/Main_Page.   

 Зураг1‐1 .NET системийн архитектур 

 

  .NET  фрэймворкын  хамгийн  чухал  гишүүн  бол  CLR  (Common  Language Runtime)  юм,  CLR  нь  програм  ажиллах  орчин  болж  өгдөг.  CLR  ийг  Java виртуаль  машинтай  адилхан  гэж  ойлгож  болно.  Виртуаль  машин  гэдэг  нь компьютерийн  платформ  болон  хэрэглэгчийн  програмын  хооронд  хиймэл орчинг бүрдүүлж харилцан ажиллах боломж олгодог системийн програм юм. CLR  нь  объектуудыг  идэвхжүүлж,  тэдгээр  дээр  шалгалт  хийж,  санах  ойд ачаалж, ажиллуулж, мөн тэдний ашиглахгүй орхисон санах ойн үлдэгдэлүүдийг нь цэвэрлэж байдаг.  .NET фрэймворк нь дараахь хэсгүүдээс бүрддэг: 

• Үндсэн хэлүүд1: C#, J#, VB.NET, Managed C++, JScript.NET • CLR    ‐  энэ  нь  дээрх  бүх  хэлүүд  хоорондоо  хамтран  ашиглах Windows болон Веб хөгжүүлэлтэд зориулсан объект хандлагат платформ юм. 

• Framework Class Library  (FCL)  гэж нэрлэгдэх хоорондоо хамаарал бүхий классуудын сан.  

 .NET нь хэлний эрх чөлөөнөөс гадна хэлний нэгдмэл байдлыг хангадаг. Энэ нь өөр  өөр  хэл  дээр  бичигдсэн  классуудын  хооронд  удамшуулах,  алдаа  барих, 

                                                 1 Мөн CLR дээр ажиллах COBOL, Python, Fortran, Smalltalk зэрэг олон тооны хэлүүд бий болсон

Page 3: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐3‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

полиморф хийх давуу талтай юм. Энэ боломжийг Common Type System  (CTS) гэж нэрлэгдэх тодорхойлолтын тусламжтайгаар бий болгодог. Тухайлбал, .NET дэх бүх зүйл нь System.Object гэж нэрлэгдэх язгуур классын объектууд юм. CTS нь  класс,  интерфэйс,  төлөөлөгч2,  заалт  төрөл3,  үндсэн  төрөл  зэрэг  ерөнхий ухагдахуунуудыг өөртөө агуулдаг.  Мөн  .NET нь хэл хоорондын нэгдмэл байдлыг хангахад зориулагдсан Common Language  Specification  (CLS)‐г  өөртөө  агуулдаг. CLS  нь  .NET  хэл  байх  хамгийн доод  шаардлагуудыг  тодорхойлсон  байдаг.    FCL  нь CLS‐тэй  тохирдог  ямар  ч хэлнээс ашиглаж болох классуудыг агуулсан сан юм.  .NET Фрэймворкын үндсэн  классуудын  санг Framework Class Library  (FCL)  гэх ба  энэ нь  түүхэнд байсан  томоохон классын  сангуудын нэг болох юм. 5000‐аас илүү  тооны  классуудыг  өөртөө  агуулсан  FCL  нь  дэсктоп,  клиент/сервер,  вэб үйлчилгээ  болон  бусад  програм  хангамжуудыг  хөгжүүлэх  ажлыг  үлэмж хөнгөвчилдөг.  FCL‐н  доод  түвшин  болох  үндсэн  классуудын  сан  нь  үндсэн  оролт/гаралт, тэмдэгт мөр боловсруулалт, хамгаалалтын менежмент, сүлжээний холболтууд, параллель боловсруулалт, өгөгдлийн бүтцийн үйлдлүүд зэргийг дэмждэг.  Үүний дээрх давхарга нь өгөгдлийн менежмент, XML боловсруулалтыг дэмжих зорилгоор  үндсэн  суурь  классуудыг  өргөтгөсөн  классууд  юм.  Классууд  нь стандарт  SQL  хэлээр  дамжуулан  өгөгдлийг  удирдах  боломж  олгодог,  энэ классуудын олонлогыг ADO.NET гэж нэрлэдэг. Мөн XML өгөгдөл боловсруулах, XML хайлт хийх боломжтой классууд байдаг.  Өгөгдлийн  болон  суурь  классуудыг  өргөтгөж  гурван  өөр  технологиор  програм хөгжүүлэхэд  зориулж  тоноглосон  байна: Web  Services, Web  Forms, Windows Forms.  Вэб  үйлчилгээний  сан  нь  firewall  болон  NAT  програмын  асуудал тулгарсан ч ажиллах чадвартай, сүлжээний орчны авсаархан үйлчилгээнүүдийг хөгжүүлэхэд зориулсан классуудыг агуулна. Вэб үйлчилгээнүүд нь HTTP болон SOAP  протоколуудыг  холболтдоо  ашигладаг  учраас  энэ  нь  сүлжээний  орон зайд чөлөөтэй ажиллах боломжтой болгодог.  Web Forms болон Windows Forms сангууд нь веб болон виндоуз орчны програм хангамжуудыг  Хурдан  Хугацаанд  Хөгжүүлэх  (Rapid  Application  Development) боломж олгоно. Контролуудыг зүгээр л чирч тавих замаар програмын цонхон дээр  оруулж,  double‐click  хийж  харгалзах  үзэгдэл  боловсруулалт  хийх  кодыг бичнэ. 

1.3 Х�рв��лэлт ба MSIL

                                                 2 delegate төрөл, C хэлний функцийн заагчтай төстэй 3 reference type – C# дахь бүх объектууд нь заалт төрөлд хамаарна  

Page 4: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐4‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

.NET‐д  програмууд  нь  машины  биелэгдэх  код  руу  хөрвүүлэгддэггүй,  харин Microsoft  Intermediate Language  (MSIL)  код  руу  хөрвүүлэгддэг,  энэ  нь CLR‐аар ажиллах боломжтой тусгай код4 юм. C# хэлний үүсгэдэг MSIL (ихэвчлэн IL гэж товчилдог)  нь  өөр  хэлнүүдийн  үүсгэдэг  IL  файлтай  ижилхэн  байдаг.  Үүний ачаар .NET нь хэл хамааралгүй платформ болж чаддаг.  Програмаа хөрвүүлэх үед C# код нь IL руу хөрвүүлэгддэг. IL нь диск дээр файлд хадгалагдана.  Програмаа  ажиллуулах  үед  IL  код  нь  Just  In  Time  (JIT) хөрвүүлэгчээр дахин хөрвүүлэгддэг (энэ процессыг ихэвчлэн JIT’ing гэж хэлдэг). Үр дүнд нь машины код гарч машины процессор үүнийг биелүүлдэг байна.  Стандарт  JIT  хөрвүүлэгч  нь  идэвхжихэд  бэлэн  горимд  ажилладаг.  Програм дуудагдсан  үед  JIT  хөрвүүлэгч  нь  IL  код  дээр  шинжилгээ  хийгээд  дараа  нь машинтай  зохицон  маш  хурдтай  ажиллах  машины  кодыг  үүсгэдэг.  JIT хөрвүүлэгч  нь  програм  ажиллаж  байх  үед  код  хөрвүүлэгдсэн  эсэхийг  таних чадвартай  учраас    шаардлагатай  үед  л  хөврүүлэлт  хийгддэг.  .NET  програм ажиллахдаа  урьдчилан‐хөрвүүлэгдсэн  кодыг  дахин  ашиглаж  улам  хурдтай ажиллахыг тэмүүлдэг байна.  

  

                                                 4 Java байт кодтой төстэй

Page 5: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐5‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Ассемблай гэдэг нь IL кодыг агуулсан Dynamic Link Library (DLL) эсвэл биелэх файлыг  (EXE)  хэлнэ.  Ассемблай  бол  програмын  дахин  ашиглагдах  (reuse), хувилбарлах  (versioning),  нууцлах  (security),  зөөвөрлөн  байршуулах (deployment)  үндсэн  нэгж  нь юм. CLR  нь  ассемблайг  удирдах  классуудыг  мөн өөртөө агуулдаг.  1.4  C# хэл  C# бол шинэ хэл юм, гэхдээ сүүлийн хэдхэн жилийн дотор маш олон програм зохиогчдын сонирхолыг татаж чадсан хэл юм.   Энэ  хэл  нь  маш  энгийн  бөгөөд  ердөө  80  түлхүүр  үг,  12  үндсэн  өгөгдлийн төрөлтэй.  Тийм  боловч  C#  нь  орчин  үеийн  програмчлалын  асуудлуудыг шийдэхэд маш тохиромжтой, үр бүтээмж өндөртэй  хэл юм. C#  нь C++  болон Java хэлнээс удамшин үүссэн бөгөөд объект хандлагат, компонентод суурилсан, бүтцийн програмчлалуудыг дэмждэг.  C#  хэлийг  Microsoft‐н  инженерүүд  болох  Anders  Hejlsberg,  Scott  Wiltamuth нараар удирдуулсан цомхон баг хөгжүүлсэн юм. Hejlsberg нь хамгийн түгээмэл PC  хэл  болох  Turbo  Pascal  хэлийг  үүсгэгчдийн  нэг  бөгөөд  мөн  Borland Delphi хэлийг хөгжүүлсэн багийг удирдаж байсан юм.  

C# програм бичиж эхлэх  Уламжлалт  “Hello  World”  програмаа  бичиж  эхлэе.  Доорх  жижигхэн програмаар C# хэлний түлхүүр онцлогуудыг гаргахыг оролдоё.  class HelloWorld {   static void Main() {     // системийн консоль объектыг ашиглаж байна     System.Console.WriteLine(“Hello World”);   } }  HelloWorld –г  хөрвүүлээд ажиллуулахад “Hello World”  гэсэн  текстийг  консоль (текст  командын  горимд  ажилладаг)  дээр  харуулна.  Энэ  жижигхэн  програм дээр илүү дэлгэрэнгүй цааш авч үзэе.  1.5 Класс, Объект, Төрөл  Объект хандлагат програмчлалын үндэс суурь бол шинэ төрлүүдийн үүсэн бий бололт  юм.    Төрөл  гэдэг  нь  нэг  зүйл  юм.  Зарим  тохиолдолд  зүйл  гэдэг  нь өгөгдлийн  хүснэгт,  thread  гэх  мэт  хийсвэр,  зарим  тохиолдолд  цонхон  доторх товчлуур гэх мэт бодитой байдаг. Төрөл нь зүйлүүдийн ерөнхий нийтлэг шинж чанар (property), авирыг (behavior) тодорхойлдог.   

Page 6: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐6‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Жишээлбэл,  програмд Help, Ok, Cancel  гэсэн  гурван  товчлууртай  гэж  бодоё. Эдгээр  тус  бүрдээ  өөрийн  хэмжээ,  байрлал,  гарчигтай.  Мөн  бүгд  зурагдах, идэвхжих, дарагдах гэх мэт нийтлэг авиртай. Иймээс хэдийгээр бие биенээсээ ялгагдах боловч эд бүгдээрээ нэг төрлийнх юм.  Объект  хандлагат  прорамчлалын  хэлэнд  байдаг  шиг  C#  ‐д  төрөл  нь  классаар тодорхойлогддог. Классын төлийг5 нь объект гэж нэрлэдэг.   “Hello World”  програмд  нэг  төрөл  тодорхойлогдсон  байна,  тэр  нь HelloWorld класс  юм.  C#‐д  төрлийг  классаар  тодорхойлох  ба  class  гэсэн  түлхүүр  үгийг ашигладаг, тэгээд нэр өгнө ‐ энэ тохиолдолд нэр нь HelloWorld, дараа нь түүний шинжүүд, авируудыг тодорхойлдог.  

Методууд

Класс нь шинж чанар,  авир хоёуланг өөртөө  агуулдаг. Авир нь түүний гишүүн методуудаар тодорхойлогддог. Шинж чанарыг дараагийн сэдвээр авч үзэе.  Метод  гэдэг нь класс доторх функц юм. Заримдаа методыг  гишүүн функц  гэж нэрлэдэг. Методууд WriteLine(), AddNumbers() гэх мэт нэртэй байна. Дээрх жишээнд класс нь Main() гэж нэрлэгдэх тусгай нэртэй методыг агуулсан байна, энэ тодорхойлолт нь классын үндсэн буюу эхний метод юм шүү гэдгийг CLR‐д хэлж  өгдөг.  Програм  ажиллаж  эхлэхэд  CLR  нь  Main()  функцийг  дууддаг.  C# програм болгон Main() методтой байх ёстой.   Зарчмын  хувьд  програмд  хэд  хэдэн  Main()  метод  байж  болох  ба  /main директивыг ашиглан аль классын Main() метод нь тухайн програмын эхлэх цэг болох вэ гэдгийг зааж болно.  Метод тодорхойлолт нь дараахь байдалтай.  int myMethod(int size);  Энэ  тодорхойлолт  нь myMethod  нэртэй  метод  size  хувьсагчаар  дамжуулан  нэг параметерийг  хүлээн  авах  ба  бүхэл  тоон  утгыг  үр  дүн  болгон  гаргана  гэдгийг хэлж байна.   Зарим методууд үр дүн буцаадаггүй, энэ тохиолдолд түүнийг void буцааж байна гэж хэлдэг. Жишээ нь:  void myVoidMethod( );

Тайлбар хийх

                                                 5 Instance – Төл, нэг хувь, нэг хуулбар

Page 7: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐7‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

C# програм дотор мөн тайлбар бичигдэж болно.   // системийн консоль объектыг ашиглаж байна Хоёр налуу зураасаар эхэлсэн мөр нь тайлбар гэдгийг илэрхийлдэг. Тайлбар нь програм зохиогчийн бичсэн тэмдэглэгээ бөгөөд програмын ажиллагаанд нөлөө үзүүлэхгүй. C# хэлэнд тайлбарыг гурван янзаар хийж болно.  Эхнийх  нь,  //‐аар  эхлээд  тухайн мөрийн төгсгөл  хүртэл  нэг мөр  тайлбар  байж болно.  Хоёр дахь нь, /*‐ээр эхлүүлж */ –ээр дуусгаж олон мөр тайлбар хийж болно.  Гурав  дахь  нь,  кодыг  XML  дээр  суурилсан  баримттай  холбож  тайлбар  хийх боломжтой байдаг. Үүнийг дараа үзнэ. 

Консоль програм

“HelloWorld” програм нь консоль ангиллын програм юм. Консоль програм нь товч,  сонголт  зэрэг  хэрэглэгчийн  график  интерфэйс  байхгүй,  зөвхөн  текст өгөгдөл  оруулах,  гаргах  үйлдлүүд  хийгддэг  програм  юм  (MS‐DOS програмуудтай төстэй).   Дээрх програмд консоль руу гаралт нь Console классаар хийгдэж байна, Console класс  нь  стандарт  гаралт  рүү  текстийг  хэвлэх  WriteLine()  методтой  байдаг. Методыг дуудахдаа (.) цэг үйлдлийг ашиглана. 

Нэрмуж

.NET  системийн  классын  санд ArrayList, Dictionary,  Event  гэх  мэт  хэдэн  арав, хэдэн  зуун  мянган  нэрсүүд  байдаг.  Эдгээр  нэрсийг  ялгахад  асуудал  үүсдэг. Програм  зохиогч  тэдгээр  нэрсийг  бүгдийг  нь  санаж  чадахгүй,  мөн  аль  нэг нэртэй  нь  ижил  нэртэй  өөрийн  гэсэн  классыг  үүсгэх  үед  асуудал  гарна.  Тухайлбал, програм зохиогч өөрийн Dictionary нэртэй классыг үүсгэхийг хүсэж болно,  гэтэл  энэ  нь  .NET‐д  байдаг Dictionary  классын  нэртэй  зөрчил  үүсгэнэ, учир нь класс бүр үл давхардах нэртэй байх ёстой байдаг.  Үүнийг шийдэх шийдэл нь нэрмуж6 юм. Нэрмуж нь тодорхой зүйлсийг нэгэн нэрийн дор хамаатуулан утга учиртай нэрлэх боломж олгодог юм.  

Том, жижиг �сг��д

C# хэлэнд нэрний үсгийн том, жижиг нь ялгаатай, ө.х writeLine ба WriteLine нь ялгаатай  юм.  Тиймээс  програмын  код  дахь  хувьсагч,  функц,  тогтмолын нэрсүүдийг тодорхой дүрмийн дагуу нэршиж занших нь зүйтэй.  

                                                 6 namespace 

Page 8: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐8‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

static т�лх��р �г

Өмнөх жишээн дэх Main() методод өөр нэг шинж ажиглагдаж байна, энэ нь static гэсэн  түлхүүр  үгээр  эхэлсэн  байна.  static  түлхүүр  үг  нь Hello  объектыг  эхэлж үүсгэлгүйгээр Main() методыг дуудаж болно гэдгийг илэрхийлнэ.  

Програмаа х�рв��лэх, ажиллуулах

“HelloWorld” програмыг хөрвүүлэх олон арга байна. Нэг бол Visual Studio.NET хөгжүүлэлтийн  хэрэгслийн  тусламжтай  хөрвүүлж  болно.  Эсвэл  C#‐ийн командын мөрний хөрвүүлэгчийг ашиглан дараахь байдлаар хөрвүүлж болно.  

1. Програмаа hello.cs нэртэйгээр хадгална 2. Командын цонхыг нээнэ (Start‐>Run гээд cmd гэж бичнэ) 3. Командын  мөр  дээр  дараахь  командыг  бичнэ.  (хөрвүүлэгчийн  замыг тодорхойлж  өгөхийн  тулд  Path  хувьсагчид  .NET  фрэймворкын  замыг зааж өгөх хэрэгтэй) 

 csc hello.cs

4. Програмаа ажиллуулахдаа Hello гэж бичээд ажиллуулна.  

JIT (Just In Time) Хөрвүүлэлт  csc    командыг  ашиглан hello.cs  кодыг  хөрвүүлэхэд  биелэх файл  үүснэ.  Энэхүү .exe файл нь IL кодыг агуулна гэдгийг санаж байх хэрэгтэй.  Сонирхолтой  нь,  хэрэв  энэ  програмыг  VB.NET  юмуу  өөр  хэл  дээр  бичээд хөрвүүлэхэд адилхан IL үүсэх болно. Өөр хэлнүүдээс үүссэн IL нь бараг ялгагдах боломжгүй байдаг.   Хөрвүүлэгч нь  IL код дээр нэмээд стандарт Win32 биелэх файлын толгойг  .exe файлын зөвхөн‐уншигдах хэсэгт оруулдаг.               

Page 9: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐9‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц 2.3  C# хэлний үндэсүүд 

Дэд сэдвүүд: • Үндсэн төрлүүд (тогтмол,хувьсагч, илэрхийлэл) • Үйлдлүүд (энгийн, арифметик, жиших, нөхцөлт, логик үйлдэл, үйлдлийн

зэрэглэл) • Заавар 

 Үндсэн төрлүүд C# хэл нь хатуу төрөлтэй хэл юм. Хатуу төрөлтэй хэлэнд үүсгэж байгаа объект бүрийн  төрлийг  заавал  тодорхой  заах  ёстой.  Ингэснээр  хөрвүүлэгч  тухайн объектод  тохирсон  утгыг  оноохыг  шаарддаг,  энэ  нь  мөн  алдаа  гаргахаас сэргийлдэг.   Өгөгдлийн  төрөл нь  хөрвүүлэгчид  тухайн объектын  хэмжээ  (жнь, int төрөл нь 4 байт объектыг заана), авируудыг мэдээлдэг (жнь, Button нь зурах, дарах гэх мэт авиртай).  C#‐ийн төрлүүдийг хоёр ангилалд хуваана: үндсэн төрөл (value type), заалт төрөл (reference type). Үндсэн төрөл болон заалт төрлийн хоорондох  ялгаа бол санах ойд  утгуудаа  яаж  хадгалж  байгаа  арга  юм.  Үндсэн  төрөл  нь  өгөгдлөө  стект хадгалдаг.  Заалт  төрлийн  хувьсагчийн  хаяг  нь  стект  байрлана,  харин жинхэнэ объект нь хийпэд7 байрладаг.  Стек ба Хийп  Стек гэдэг нь “эхэлж орсон нь сүүлд гарах“ зарчмаар элементүүдийг хадгалдаг өгөгдлийн  бүтэц  юм.  Энд  дурдсан  стек  нь  локаль  хувсагчидыг  хадгалах  санах ойн мужийг хэлж байна.  C#  хэлэнд  үндсэн  төрлүүд  нь,  жишээ  нь  integer,  стект  хувиарлагдах  бөгөөд хувьсагчийн нэр нь санах ойн хаягаа илэрхийлж байдаг.  Заалт  төрлүүд  нь  (жнь,  object)  хийпэд  хувиарлагддаг.  Объект  хийпэд хувиарлагдах  үед  түүний  хаяг  нь  буцаагдах  ба  энэхүү  хаяг  нь  заалт  болон хувьсагчид оноогддог.  Хог цуглуулагч8  нь  объектын  зарлагдсан  стек  хүрээ  дууссанаас  хойш  хэсэг хугацааны  дараа  тэрхүү  объектыг  санах  ойгоос  устгадаг.  Стек  хүрээ  гэдэг  нь үндсэндээ функцүүдээр  тогтоогддог.  Тухайлбал, функц  дотор  локаль  хувьсагч зарлавал уг функ ажиллаж дууссаны дараа үлдэгдэл цуглуулагч түүнийг устгах ёстой гэдгийг ойлгох болно.  Хийп  дэх  объектуудын  хувьд  түүнийг  зааж  байгаа  хамгийн  сүүлийн  заалт                                                  7 Heap – санах ойн нэг төрлий н муж 8 Garbage collector 

Page 10: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐10‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

устсанаас  хойш  хэсэг  хугацааны  дараа  уг  объект    үлдэгдэл  цуглуулагчаар устгагддаг.    C# хэлэнд орчин үеийн хэлэнд байвал зохих бүх үндсэн төрлүүд байдаг бөгөөд эдгээр нь харгалзан  .NET CLS  төрөл рүүгээ бууж байдаг. C#  төрлийг  .NET рүү харгалзуулсан  буулгалт  нь C#  дээр  үүсгэгдсэн  объект  өөр  хэл  дээр  үүсгэгдсэн объекттой харилцан ажиллах боломжийг олгодог.  Төрөл бүр санах ойд тогтмол хэмжээ эзэлдэг.   Төрөл  Хэмжээ(байт)  .NET төрөл  Тодорхойлолт byte  1  Byte  Байт, 0‐255 char  1  Char  Юникод тэмдэгт bool  1  Boolean  true эсвэл false sbyte  1  Sbyte  Тэмдэгтэй байт, ‐128 ‐ 127 short  2  Int16  Бага бүхэл тоо (‐32768 ‐ 32767) ushort  2  Uint16  Тэмдэггүй бага бүхэл тоо, 0 ‐ээс 216‐1 int  4  Int32  Бүхэл тоо ‐(231‐1) –ээс  (231‐1) uint  4  Uint32  Тэмдэггүй бүхэл тоо, 0 ‐ээс 232‐1 float  4  Single  Бодит тоо, ±1.5*10‐45 ээс ±3.4*1038 double  8  Double  Давхар  нарийвчлалтай  бодит  тоо,  ±5.0*10‐324  ээс 

±1.7*10308 decimal  8  Decimal  28  хүртэл  цифртэй,  тогтмол  нарийвчлалтай 

бутархай  тоо.  Энэ  нь  ихэвчлэн  санхүүгийн тооцоололд  ашиглагддаг.  “m”  эсвэл  “M”  гэсэн дагаваруудыг хэрэглэдэг. 

long  8  Int64  Их бүхэл тоо, ‐9,223,372,036,854,775,808 ээс 9,223,372,036,854,775,807 

ulong  8  Uint64  Тэмдэггүй их бүхэл тоо, 0 ээс 0xffffffffffffffff  Эдгээр  үндсэн  төрлүүдээс  гадна C#  хэлэнд  enum  ба  struct  гэсэн  үндсэн  төрлүүд байдаг.  

�ндсэн т�рл��с сонгож хэрэглэх

Ерөнхийдөө  ямар  хэмжээтэй  бүхэл  тоон  төрөл  (short,  int  эсвэл  long)  сонгох  вэ гэдэг  нь  ямар  хэмжээтэй  өгөгдөл  хадгалах  вэ  гэдгээс  хамаарна.  Жишээлбэл, ushort төрөл нь 0‐ээс 65535 хүртэлх тоон утгыг хадгалж чадна.  Санах ой хангалттай байгаад онцын өөр шалтгаан байхгүй бол int төрлийг ихэнх тохиолдолд хэрэглэх нь зүйтэй.  

Тогтмол ба Хувьсагч

Хувьсагч гэдэг нь тодорхой төрөл бүхий санах ойн хадгалах үүр юм. Хувьсагчид утга оноож болно мөн тэрхүү утга нь програмын ажиллах үед өөрчлөдөнө.  

Page 11: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐11‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Хувсагчийг зарлахдаа түүний төрөл, нэрийг зааж өгөх ёстой. Хувьсагчийг зарлах үед түүнд анхны утгыг оноож өгч болно.   class Values { static void Main( ) { int myInt = 7;

System.Console.WriteLine("Initialized, myInt: {0}", myInt); myInt = 5; System.Console.WriteLine("After assignment, myInt: {0}", myInt);

} }  Энэ  жишээн  дээр myInt  хувьсагчийг  зарлах  үедээ  түүнд  7  гэсэн  анхны  утга оноож байна, тэгээд түүний утгыг хэвлээд дараа нь 5 гэсэн утгыг дахин оноож дахин хэвлэж байна.  

WriteLine( )  Дээрх  жишээнд WriteLine  методын  өөр  нэг  хэлбэрийг  ашигласан  байна.  Энэ жишээнд WriteLine  метод  нь  2  параметр  хүлээн  авах  ба  эхний  параметр  нь өгөгдлийг  хэвлэх  форматыг    “Initialized, myInt:  {0}”  хэлбэртэй  гэж  тодорхойлно,  хоёр  дахь  нь  хэвлэгдэх  хувьсагчийн  нэр.  Энд  {0}  бичиглэл  нь  эхний  хувьсагч гэдгийг заана.   C#  хэл нь хувьсагчийн ашиглахын өмнө  заавал утга оноосон байхыг шаардана. Энэ дүрмийг шалгахын тулд myInt хувьсагчид утга оноолгүйгээр дээрх жишээг өөрчилж үзэж болно.  class Values { static void Main( ) { int myInt;

System.Console.WriteLine("UnInitialized, myInt: {0}", myInt); myInt = 5; System.Console.WriteLine("Assigned, myInt: {0}", myInt);

} }  Энэ програмыг хөрвүүлэх үед C# хөрвүүлэгч дараахь алдааг заана.  values.cs(6,55): error CS0165: Use of unassigned local variable 'myInt'  Тэгэхээр програм дахь  хувьсагч бүрийг  зарлахдаа анхны утга оноох  ёстой юу? Үгүй,  заавал  анхны  утга  оноох  хэрэггүй,  гэхдээ  заавал  ашиглахын  өмнө  утга оноосон байх хэрэгтэй гэсэн үг.  

Page 12: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐12‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

class Values { static void Main( ) { int myInt; myInt = 7;

System.Console.WriteLine("UnInitialized, myInt: {0}", myInt); myInt = 5; System.Console.WriteLine("Assigned, myInt: {0}", myInt);

} }  

Нэр

Хувьсагч  нь  нэртэй  байх  бөгөөд нэр  нь  үсгээр  эсвэл  доогуур  зураасаар  эхлэх ёстой.  Нэрэнд  үсгийн  том,  жижиг  нь  ялгаатай  байдаг,  myVariable  ба  MyVariable нэрнүүд нь ялгаатай юм. C# хэлэнд өөрийн гэсэн тогтсон нэрлэх дүрэм байдаг, хувьсагчдын  хувьд  Камель  тэмдэглэгээ  (жнь,  someVariableName),  метод  болон бусад нэрнүүдийн хувьд Паскаль тэмдэглээг (жнь, SomeFunction) ашигладаг.  Камель  ба  Паскаль  тэмдэглээний  ялгаа  гэвэл  Паскаль  тэмдэглэгээнд  нэр  нь том үсгээр эхэлдэг.  Нэр  нь  түлхүүр  үгтэй  адил  байж  болохгүй.  Ө.х  int  эсвэл  class  гэсэн  нэртэй хувьсагчид байж болохгүй.   

Тогтмол

Тогтмол  гэдэг  бол  түүний  утгыг  нь  өөрчлөх  боломжгүй  хувьсагч  юм.  Зарим тохиолдолд хувьсагчийн утга өөрчлөгдөхгүй байх хэрэгцээ гардаг.   Тогтмол  нь  3  хэлбэрээр  байж  болно:  эх  хэлбэрээрээ,  нэрлэсэн  тогтмол, тоочсон тогтмол.   x = 32;  Энд 32 гэсэн тоо нь эх хэлбэрээрээ байгаа тогтмол юм. Ө.х 32‐н утга бол үргэлж 32 байна, 32‐д шинэ утга оноож чадахгүй, өөрчилж чадахгүй.  Нэрлэсэн тогтмол нь тогтмол утгад нэр оноосон хэлбэр юм. Дараахь байдлаар ийм тогтмолыг зарлаж болно.  const type identifier = value;  Тогтмол нь зарлагдах үедээ анхны утга нь оноогдсон байх ёстой. 

Page 13: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐13‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 const int FreezingPoint = 32;  Энд 32 нь эх хэлбэрээрээ байгаа тогтмол, FreezingPoint нь нэрлэсэн тогтмол юм.  using System; class Values { static void Main( ) {

const int FreezingPoint = 32; // degrees Farenheit const int BoilingPoint = 212; Console.WriteLine("Freezing point of water: {0}", FreezingPoint ); Console.WriteLine("Boiling point of water: {0}",BoilingPoint ); //BoilingPoint = 21;

} }

Тоочсон тогтмол

Тоочих  төрөл  нь  тогтмолын  өөр  нэг  хувилбар  юм.  Тоочих  төрөл  нь  тодорхой тооны нэрлэсэн‐тогтмолуудын олонлог юм. Өмнөх жишээн дэх   const int FreezingPoint = 32; const int BoilingPoint = 212;  тогтмолууд дээр  const int LightJacketWeather = 60; const int SwimmingWeather = 72; const int WickedCold = 0;  тогтмолуудыг  нэмэх  хэрэгтэй  гэж  үзэе.  C#‐д  enum  тоочих  төрөл  нь  энэ боломжийг олгоно.  enum Temperatures { WickedCold = 0,

FreezingPoint = 32, LightJacketWeather = 60, SwimmingWeather = 72, BoilingPoint = 212,

}  Ерөнхийдөө, тоочсон тогтмолыг зарлах хэлбэр нь дараахь байдалтай.  [attributes] [modifiers] enum identifier [:base-type] {enumerator-list};  attributes, modifiers –н тухай дараа үзнэ. base‐type нь тухайн тоочилтын суурь төрөл нь юм.  Хэрэв  энэ  заалтыг  орхивол  тухайн  тоочсон  утгуудыг  integer  байна  гэж ойлгодог. Мөн бусад тоон төрлүүдийг ашиглаж болно. Жишээ нь, ushort, uint  

Page 14: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐14‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

enum ServingSizes :uint { Small = 1, Regular = 2, Large = 3

}  Тоочих  төрөл дэх  тогтмол бүр  түүнд  харгалзах  тоон  утгатай  байдаг,  хэрэв  энэ утгыг  зааж  өгөхгүй  бол  0‐ээс  эхлэн  дараалуулан  автоматаар  өмнөх  утга  дээр нэгийг нэмсэн утга олгогдох болно. Жишээ нь:  enum SomeValues {

First, Second, Third = 20, Fourth

}  Энд First=0, Second=1, Third=20, Fourth=21 болох юм.   Тоочих  төрөл  нь  хийсвэр  төрөл  юм,  тиймээс  тоочих  төрөл  болон  бүхэл  тоон төрлийн хооронд хөрвүүлэлт хийх бол ил хөрвүүлэлт хийхийг шаарддаг. 

Тэмдэгт м�р тогтмол

Мөр тогтмол нь тэмдэгтүүдийн дараалал юм. Тэмдэгт мөр төрлийн хувьсагчийг string түлхүүр үгээр зарлана.  string myString;  Тэмдэгт мөр утга нь давхар хашилтад хийгдэж бичигдэнэ:  “Hello World”  Анхны утга оноосон тэмдэгт мөр төрлийн хувьсагч:  string myString = “Hello World”;  

Илэрхийлэл

Үр  дүндээ  утга  гаргадаг  хувьсагч,  тогтмол,  объект,  үйлдлүүдийн  дараалсан нийлэмжийг илэрхийлэл гэдэг. Жишээлбэл,   myVariable = 57 нь илэрхийлэл юм. Учир нь энэ нь 57  гэсэн утгыг үр дүн болгон гаргаж байна.   Энд  (=) тэмдэгт нь утга оноох үйлдэл юм (тэнцүүлэх үйлдэл биш!).  myVariable  =  57  нь  илэрхийлэл  учраас  өөр  илэрхийлэл  дотор  мөн  оролцож болно.  

Page 15: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐15‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

mySecondVariable = myVariable = 57;  Энэ жишээнд  57  утга myVariable  хувьсагчид  оноогдож байна,  энэ  олголтын  үр дүн нь дахиад хоёр дахь хувьсагч болох mySecondVariable‐д оноогдож байна.   Илэрхийлэлд илүү сул зайнуудыг оруулж болно. Жишээлбэл,  myVariable = 5;эсвэл: myVariable = 5;  Хөрвүүлэгч  нь  дээрх  хоёр  зааврыг  адилхан  гэж  үзнэ.  Гэхдээ  энэ  дүрэм  нь тэмдэгт мөр тогтмолын хувьд буруу болох юм. Ө.х “Hello World” ба “Hello        World” тэмдэгт мөрүүд нь ялгаатай.  Сул  зайг  ихэвчлэн  програмыг  уншихад  илүү  ойлгомжтой  болгох  зорилгоор ашигладаг, хөрвүүлэгчийн хувьд энэ нь ялгаагүй зүйл. 

�йлдэл

Энгийн  тооцоолол  хийхэд  олгох,  нэмэх,  хасах  гэх  мэт  олон  үйлдлүүдийг ашигладаг.  

Олгох �йлдэл (=)

Энэ тэмдэгт нь олгох үйлдлийг төлөөлөх ба зүүн талд байгаа хувьсагчид баруун талд байгаа утгыг олгоход хэрэглэгддэг. 

Арифметик �йлдл��д

C#  нь  нэмэх  (+),  хасах  (‐),  үржих  (*),  хуваах  (/),  үлдэгдэл  олох  (%)  арифметик үйлдлүүдийг ашигладаг.   Хуваах үйлдлийн хувьд бүхэл 2 тоог хуваах үед ногдворын бүхэл хэсэг нь үр дүн болж  гарна.  Жишээ  нь,  17‐г  4‐д  хуваахад  үр  дүн  нь  4  болно  (17/4=4  ба  1 үлдэгдэлтэй).  Харин бодит тоог хуваах үед үр дүн нь бутархай тоо гарна.  Үлдэгдэл  олох  үйлдэл  нь  мөн тоог  ямар  нэг  тоо  өөр тоонд  бүхлээр  хуваагддаг эсэхийг шалгахад  хэрэглэгдэж  болно.    80 %  10  =  0  учраас  80  нь  10‐д  бүхлээр хуваагдана. 

Тооцоолоод олгох �йлдэл

mySalary хувьсагчийн утгыг 5000‐аар нэмэгдүүлэх хэрэгтэй гэж бодоё. Үүнийг   mySalary = mySalary + 5000;  эсвэл  

Page 16: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐16‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

mySalary += 5000;  гэж бичиж болно. C#‐д тооцоолол хийгээд гарсан үр дүнг нь олгодог += (нэмээд олгох),  ‐=  (хасаад  олгох),  *=  (үржээд  олгох),  /=  (хуваагаад  олгох), %=  (үлдэгдэл олгох) операторууд байдаг.  Хувьсагчийн  утгыг  1‐ээр  нэмэгдүүлэх,  хорогдуулах  шаардлага  олонтаа тохиолддог, үүнд зориулж ++, ‐‐ үйлдлүүд бий. Жишээлбэл,   myAge++; firstValue = secondValue++;  гэж хэрэглэж болно.  Эдгээр үйлдлүүдийг олгох үйлдэлтэй хамт хэрэглэсэн үед хувьсагчийн утгыг 1‐ээр нэмсэний дараа нөгөө хувьсагчид гарсан үр дүнг олгох уу, эсвэл олгосны дараа нь  1‐ээр  нэмэгдүүлэх  үү  гэсэн  асуулт  гарна. Үүнийг шийдэхэд  угтвар  (prefix), дагавар (postfix) бичиглэлүүдийг хэрэглэнэ.  firstValue = secondValue++; // postfix firstValue = ++secondValue; // prefix  Угтвар, дагавар операторуудын ялгааг ойлгохын тулд дараахь жишээг харая.  using System; class Values { static void Main( ) {

int valueOne = 10; int valueTwo; valueTwo = valueOne++; Console.WriteLine("After postfix: {0}, {1}", valueOne, valueTwo); valueOne = 20; valueTwo = ++valueOne; Console.WriteLine("After prefix: {0}, {1}", valueOne, valueTwo);

} } Гарах үр дүн: After postfix: 11, 10 After prefix: 21, 21

Н�хц�лт �йлдэл

Ихэнх үйлдэл нэг юмуу хоёр илэрхийллийг холбогддог. Харин нөхцөлт үйлдэл нь (?:) гурван илэрхийллийг холбодог.  cond-expr ? expr1 : expr2

Page 17: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐17‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 Энэ үйлдэл нь cond‐expr нөхцөлд бичигдсэн илэрхийллийг үнэлээд хэрэв утга нь үнэн бол expr1, худал бол expr2‐г үр дүн болгон гаргадаг.  class Values { static void Main( ) {

int valueOne = 10; int valueTwo = 20; int maxValue = valueOne > valueTwo ? valueOne : valueTwo; Console.WriteLine("ValueOne: {0}, valueTwo: {1}, maxValue: {2}",

valueOne, valueTwo, maxValue); } } Гаралт: ValueOne: 10, valueTwo: 20, maxValue: 20

Жиших �йлдэл

Жиших  үйлдэл  нь  хоёр  утгыг  харьцуулаад  үнэн  эсвэл  худал  (boolean)  утга буцаадаг оператор юм. Жишээ нь, эрс их (>) операторыг 5 > 2 гэж хэрэглэвэл үр дүн нь true, 2 > 5 гэж хэрэглэвэл үр дүн нь false болно.  Нэр  Оператор Тэнцүүлэх  == Тэнцүү биш  != Их  > Их буюу тэнцүү  >= Бага  < Бага буюу тэнцүү  <= 

Логик �йлдэл

Логик илэрхийллүүдийг9  холбоход логик үйлдлүүдийг ашигладаг.  Нэр  Оператор Ба  && Эсвэл  || Үгүйсгэл  !  Жишээ нь, (x==3) && (y==7) энэ логик илэрхийлэл нь (x==3), (y==7) гэсэн хоёр логик илэрхийллээс  тогтсон  бөгөөд  БА  (&&)  логик  үйлдлээр  холбогдсон  байна.  Энэ илэрхийллийн утга нь x нь 3‐тай тэнцүү бөгөөд y нь 7‐той тэнцүү байх үед үнэн байна.   

Богино үнэлэлт 

                                                 9 үнэн эсвэл худал утга гаргадаг илэрхийлэл 

Page 18: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐18‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 Дараахь кодыг авч үзэе.  int x=8; ((x==8) || (y==12) ? expr1 : expr2)  Энэ илэрхийллийг үнэлэхэд x нь 8‐тай тэнцүү учраас үр дүн нь true гарна. Хоёр дахь илэрхийллийг бодох шаардлага байхгүй. Ө.х y нь 12‐той тэнцүү байна уу, тэнцүү биш байна уу гэдгээс хамаарахгүй. Мөн дараахь илэрхийллийг авч үзэе.  int x=8; ((x==5) && (y==12) ? expr1 : expr2)  Энэ тохиолдолд мөн л хоёр дахь илэрхийллийг үнэлэх шаардлагагүй, үр дүн нь false утга гарах юм. Учир нь эхний x==5 илэрхийлэл false утга өгнө (&& үйлдэл нь хоёр утга хоёулаа  үнэн үед үнэн гардгийг санаарай).  Эдгээр  тохиолдлуудад C#  хөрвүүлэгч  нь  богино‐үнэлэлт  хийдэг,  ө.х  хоёр  дахь илэрхийлэл дээр хэзээ ч үнэлэлт хийгдэхгүй. 

�йлдлийн зэрэглэл

Хөрвүүлэгч  нь  илэрхийлэл  дэх  үйлдлүүдийн  биелэх  дарааллыг мэддэг. Жишээ нь,  myVar = 5 + 7 * 3;  Энэ илэрхийлэлд * үйлдэл нь + үйлдлээс өмнө үнэлэгдэх ёстой. Ө.х * үйлдэл нь + үйлдлээс өндөр зэрэглэлтэй байна.    Мөн нийлмэл  илэрхийллүүд  дотор  хаалт  хэрэглэн  үйлдлүүдийн  үнэлэх дарааллыг өөрчилж болно.   Дараахь хүснэгтэд үйлдлүүдийн биелэх дарааллыг  тодорхойллоо.  Ангилал    Үйлдлүүд Үндсэн  (x) x.y f(x) a[x] x++ x—new typeof sizeof checked unchecked Унар  + ‐ ! ~ ++x —x (T)x Үржих  * / % Нэмэх  + ‐ Шилжүүлэх  << >> Жиших  < > <= >= is Тэнцүүлэх  == != Бит Ба  & Бит XOR  ^ Бит Буюу  | 

Page 19: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐19‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Логик Ба  && Логик Буюу  || Гурван байрт  ?: Олгох  = *= /= %= += ‐= <<= >>= &= ^= |=  

3. Заавар

Зааварууд нь ямар боловсруулалт хийхийг компьютерт зааварлана. Заавруудын олонлогоос програм нь  тогтоно.    Заавар бүр цэгтэй  таслалаар  (;)  төгсөх  ёстой. Жишээлбэл,   int x; // заавар x = 23; // өөр заавар int y = x; // бас нэг заавар  Зааврууд  нь  програмд  бичигдсэн  дарааллынхаа  дагуу  биелэгддэг:  програм ажиллахдаа хамгийн эхний заавраас эхлээд сүүлийн заавар хүртэл явдаг. Гэхдээ энэ нь салаалах заавруудын тохиолдолд өөр болох юм. Хоёр төрлийн салаалах заавар байдаг: нөхцөлт салаалах болон нөхцөлгүйээр салаалах.   Програмын  биелэх  дараалал  нь  мөн  давтах  заавруудаар  өөрчлөгдөж  болно. Эдгээр нь for, while, do, in, foreach түлхүүр үгүүдээр тэмдэглэгддэг.   

3.1 Н�хц�лт бус салаалах заавар

Нөхцөлт бус салаалалт нь хоёр замаар хийгдэж болно. Эхнийх нь метод дуудалт юм.  Програм  ажиллаж  байх  үед  метод  дуудахад  тухайн  эгшинд  ажиллаж байсан  методын  биелэлтийг  зогсоогоод  шинэ  “дуудагдсан”  метод  руу салаалдаг.  Тэр  метод  нь  ажиллаж  дуусаад  утга  буцаахад  анхны  методын дараагийн мөрнөөс биелэлтийг үргэлжлүүлдэг.  using System; class Functions { static void Main( ) {

Console.WriteLine("In Main! Calling SomeMethod( )..."); SomeMethod( ); Console.WriteLine("Back in Main( ).");

} static void SomeMethod( ) {

Console.WriteLine("Greetings from SomeMethod!"); } } Гаралт: In Main! Calling SomeMethod( )... Greetings from SomeMethod! Back in Main( ).

Page 20: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐20‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 Хоёр  дахь  зам  нь  нөхцөлт  бус  салаалах  түлхүүр  үгүүдийг  ашиглах:  goto,  break, continue, return, throw.  Эдгээрийн тухай дараа дэлгэрүүлэн судлана.  

3.2 Н�хц�лт салаалах заавар

Нөхцөлт  салаалалт  нь  if,  else,  switch  зэрэг  түлхүүр  үгүүдийн  тусламжтай хийгдэнэ. Өгөгдсөн нөхцөлөөс хамааран салаалалт хийгдэнэ.  

3.2.1 If..else заавар

if..else заавар нь нөхцөлт салаалалт хийхэд ашиглагдана. Нөхцөл гэдэг нь логик илэрхийлэл юм. Энэ илэрхийллийн утга үнэн үед  if   заавар доторх командууд биелэнэ.  if  заавар  нь  else  зааврыг  агуулж  болно,  энд  нөхцөл  худал  үед  биелэх командууд бичигдэнэ.   if (expression) statement1 [else statement2]  using System; class Values { static void Main( ) {

int valueOne = 10; int valueTwo = 20; if ( valueOne > valueTwo ) {

Console.WriteLine("ValueOne: {0} larger than ValueTwo: {1}", valueOne, valueTwo);

} else {

Console.WriteLine("ValueTwo: {0} larger than ValueOne: {1}", valueTwo,valueOne);

} } }  

Зааврын блок  Зааврын  блок  гэдэг  нь  {  }  хаалтуудаар  хашигдсан  заавруудын  олонлог  юм.  Тухайлбал,  if (someCondition) { statementOne; statementTwo; statementThree; }

Page 21: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐21‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 гэж бичиж болно.  

3.2.2 Давхар if заавар

Нийлмэл  нөхцөлүүдийг  боловсруулахын  тулд  if  зааврыг  үүрлүүлж  хэрэглэж болно. Жишээлбэл,  using System; class Values { static void Main( ) {

int temp = 32; if (temp <= 32) {

Console.WriteLine("Warning! Ice on road!"); if (temp == 32) { Console.WriteLine("Temp exactly freezing, beware of water."); } else { Console.WriteLine("Watch for black ice! Temp: {0}", temp); } }

} }  Програмын  нь  агаарын  температур  32‐оос  бага  эсэхийг шалгаж  байна.  Хэрэв тийм бол  ʺWarning!  Ice on  road!ʺ  гэсэн  сэрэмжлүүлгийг  хэвлэж байна. Дараа нь 32‐той  тэнцүү  эсэхийг    шалгаж  дараагийг  мэдэгдлийг  хэвлэж  байна.  Энд  if зааврыг  if  заавар  дотор  давхар  хэрэглэсэн  байна.  Энд  байгаа  else  заавар  нь температур 32‐оос эрс бага нөхцөлд биелэх юм.  

Тэнцүүлэх оператор  C#‐д тэнцүүлэх оператор нь “==” ээр тэмдэглэгддэг.  if (temp == 32)  Үүнийг “=” утга олгох оператортай андуурч болохгүй.  

3.2.3 switch заавар

Сэлгэх  заавар нь угсраа  if  зааврын өөр нэг  хувилбар нь юм, угсраа  if  заавар нь уншихад их  төвөгтэй  байдаг. Олон  нөхцөлөөс  сонголт  хийх  тохиолдолд  сэлгэх зааврыг   ашиглах нь илүү  тохиромжтой юм. Сэлгэх зааврын логик нь тохирох утгыг олох, тэгээд биелүүлэх юм.  switch (expression) {

Page 22: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐22‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

case constant-expression: statement jump-statement

[default: statement] }  Сэлгэх зааврын толгойд логик илэрхийлэл бичигдэнэ, case  заавар бүрийн ард тогтмол  утга    тавихыг  шаардана.  Энд  эх  хэлбэрээрээ  тогтмол,  нэрлэсэн тогтмол, тоочих төрлийн тогтмолууд байж болно.  Case  зааврын ард  талын утга  тохирсон үед  харгалзах  зааврууд биелэнэ,  тэгээд үсрэлт   хийгдэх ёстой. Ерөнхийдөө, үсрэлт хийх заавар нь break юм. Эсвэл өөр заавар руу шилжих шаардлагатай бол goto зааврыг ашиглаж болно.  using System; class Values { static void Main( ) {

const int Democrat = 0; const int LiberalRepublican = 1; const int Republican = 2; const int Libertarian = 3; const int NewLeft = 4; const int Progressive = 5; int myChoice = Libertarian;

switch (myChoice) { case Democrat:

Console.WriteLine("You voted Democratic.\n"); break;

case LiberalRepublican: // fall through case Republican:

Console.WriteLine("You voted Republican.\n"); break;

case NewLeft: Console.Write("NewLeft is now Progressive"); goto case Progressive;

case Progressive: Console.WriteLine("You voted Progressive.\n"); break;

case Libertarian: Console.WriteLine("Libertarians are voting Republican"); goto case Republican;

default: Console.WriteLine("You did not pick a valid choice.\n"); break;

}

Console.WriteLine("Thank you for voting."); } }  

Page 23: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐23‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Энэ  жишээнд  улс  төрийн  бүлгүүдийг  төлөөлсөн  тогтмолууд  тодорхойлсон байна.  Дараа  нь myChoice  хувьсагчид  Libertarian  утгыг  оноосон  байна.  Хэрэв myChoice  нь  Democrat    ‐тай  тохирч  байвал  харгалзах  текстийг  хэвлэнэ.  Энэ тохиолдолд break  заавраар  төгссөн байгааг  ажиглаарай,  энэ нь  switch  зааврын гадна гарч дараагын зааврыг биелүүлэх юм.   LiberalRepublican утгын дор харгалзах заавар байхгүй байна, тийм учраас энэ нь дараагийн  заавар  болох  Republican  руу  “бууна”.  Энэ  нь  сонгогдсон  утга LiberalRepublican эсвэл Republican байх үед Republican заавар биелэнэ гэсэн үг.  Өөр заавар руу шилжих шаардлагатай үед goto зааврыг ашиглаж болно. Хэрэв аль ч тохиолдол нь таарахгүй бол default‐н ард бичигдсэн заавар биелэх болно.  Програм дараахь үр дүнг хэвлэнэ:  Libertarians are voting Republican You voted Republican. Thank you for voting.  Энэ  жишээнд  сонголт  хийгдэх  утга  нь  бүхэл  тоон  тогтмол  байна. C#  нь  мөн тэмдэгт мөр төрлийн утга дээр сонголт хийх боломж олгодог. Жишээ нь:  case “Libertarian”:  

3.3 Давтах заавар

C#‐д  үйлдлийг  давтан  гүйцэтгэхэд  зориулсан  for,  while..do,  do..while,  foreach зааврууд  байдаг.    C#  нь  мөн  goto,  break,  continue,  return  үсрэх  заавруудыг хэрэглэх боломжтой.  

3.3.1 goto заавар

Goto  заавар  нь  бусад  бүх  давтах  заавруудын  үндэс  нь юм.  Гэхдээ  энэ  зааврыг ашиглахгүй  байх  хэрэгтэй,  учир  нь  энэ  нь  кодыг  ойлгомжгүй  болгодог,  ийм төрлийн  програмыг  “шпагетти”  програм  гэж  хэлдэг.  Ихэнхи  туршлагатай програм  зохиогчид  goto  зааврыг  ашиглахаас  зайлсхийдэг,  гэхдээ  энд  яаж хэрэглэх тухай дурдая.  

1. Тодорхой байрлалд хаяг (label) тодорхойлно 2. Дараа нь хаа нэг газраас энэ хаяг руу goto‐ээр үсрэнэ 

 using System; public class Tester { public static int Main( ) {

int i = 0;

Page 24: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐24‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

repeat: // the label Console.WriteLine("i: {0}",i); i++; if (i < 10) goto repeat; // the dasterdly deed return 0;

} }  Хэрэв  goto  заавар  олон  ашигласан  програмын  командын  биелэх  дарааллыг зурж  үзвэл  бие  биен  дээгүүрээ  үсэрсэн,  огтлолцсон шпагетти‐тэй  төстэй  дүр зураг харагдана. Эндээс “шпагетти програм” гэсэн нэр томъёо үүссэн юм.  

3.3.2 while давталт

while  давталтын  үндсэн  санаа  нь  “энэ  нөхцөл  биелж  байвал  энэ  ажлыг  хий” гэсэн утга юм.   while (expression) statement  Энд илэрхийлэл нь логик илэрхийлэл байх ёстой.  using System; public class Tester { public static int Main( ) {

int i = 0; while (i < 10) { Console.WriteLine("i: {0}",i); i++; } return 0;

} }  Энэ  код  нь  өмнөх  goto‐н  жишээн  дэх  кодтой  ижил  үйлдэл  хийнэ.    Гэхдээ програмын  логик  нь  илүү  ойлгожтой  харагдаж  байна.  while  заавар  нөхцөл худал үед нэг ч удаа биелэхгүй.  

3.3.3 do..while давталт

Зарим  тохиолдолд  “үнэн  үед  үүнийг  гүйцэтгэ”  гэсэн  өгүүлбэрээ  “үүнийг гүйцэтгэ, үнэн байх үед давт” гэж өөрчлөх хэрэг гарч болно. Ө.х үйлдэл эхлээд хийгдэнэ,  үүний  дараа  шалгалт  хийгдэнэ.  Энэ  зорилгоор  do..while  давталтыг ашиглаж болно.  do expression while statement  

Page 25: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐25‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Жишээ нь,  using System; public class Tester { public static int Main( ) {

int i = 11; do { Console.WriteLine("i: {0}",i); i++; } while (i < 10); return 0;

} }  Энд  i хувьсагчийн анхны утга 11 байна, тиймээс while дахь нөхцөл тохирохгүй, гэвч давталт доторхи заавар нэг удаа ажиллах юм.  

3.3.4 for давталт

Өмнөх  давтах  заавруудаас  харахад  дараахь  хэв  загварын  зааврууд  олон тааралдаж байна: хувьсагчид анхны утга оноох (i = 0), нөхцөл шалгах (i < 10) , хэсэг зааврыг биелүүлэх, мөн хувьсагчийн утгыг өөрчлөх  (i++). For давталт нь энэ бүх алхмуудыг нэг дор нэгтгэж өгдөг.  for ([initializers]; [expression]; [iterators]) statement  Жишээ нь,  using System; public class Tester { public static int Main( ) {

for (int i=0; i<100; i++) { Console.Write("{0} ", i); if (i%10 == 0) {

Console.WriteLine("\t{0}", i); }

} return 0;

} }  Энэ жишээнд  10‐д  үлдэгдэлгүй  хуваагдах  тоонуудыг  хэвлэж  байна.  Хэвлэхдээ Console.Write  методыг  ашигласан  байна,  энэ  нь WriteLine  –тай  адил  боловч шинэ мөрөнд шилжихгүй үргэлжлүүлж хэвлэдэгээрээ ялгаатай.   Энд  зарласан  i  хувьсагч  нь  for  давталтын  хүрээн  дотроо  л  үйлчлэх  юм.  Ө.х дараахь мөрийг нэмбэл хөрвүүлэгч алдаа заах болно.  

Page 26: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐26‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

using System; public class Tester { public static int Main( ) {

for (int i=0;i<100;i++) { Console.Write("{0} ", i); if (i%10 == 0) {

Console.WriteLine("\t{0}", i); }

} Console.WriteLine("\n Final value of i: {0}", i); return 0;

} }    

Сул зай ба Хаалт  Сул  зай  ба  хаалтыг  ямар  байдлаар  хэрэглэх  нь  програм  зохиогчийн  дурын хэрэг  боловч код уншихад хялбар байлгахыг бодох хэрэгтэй. Жишээлбэл,   for (int i=0;i<100;i++) { Console.Write("{0} ",i); if (i%10==0) Console.WriteLine("\t{0}", i); } кодын  нээх  хаалтуудыг  шинэ  мөрөнд  оруулж,  үйлдлүүдийн  хооронд  сул  зай аван дараахь байдлаар бичиж болно.  for (int i=0; i<100; i++) { Console.Write("{0} ", i); if (i%10 == 0) { Console.WriteLine("\t{0}", i); } }  Энэ нь илүү уншихад ойлгомжтой  бичиглэл юм.  

3.3.5 foreach давталт

Энэ  давталт  нь C  төрлийн  програм  зохиогчдын  хувьд  шинэ  зүйл  юм,  гэхдээ Visual Basic програм зохиогчдын хувьд танил байх. Энэ давталт нь массив болон бусад өгөгдлийн бүтцийн бүх элементүүдээр давталт хийхэд хэрэглэгддэг.  foreach (type identifier in expression) statement  Жишээ: 

Page 27: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐27‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 using System; public class Tester { static void Main() {

int[] intArray; intArray = new int[5]; // populate the array for (int i = 0;i<intArray.Length;i++) { intArray[i] = i; } foreach (int i in intArray) { Console.WriteLine(i.ToString()); }

} }  

3.3.6 continue ба break зааврууд

Зарим  тохиололд  давталт  доторх  үлдсэн  хэсгийг  билүүлэлгүйгээр  давталтыг шинэчлэн эхлүүлэх шаардлага гардаг. continue заавар нь давталтын удирдлагыг дахин эхэнд нь аваачиж биелүүлэхэд хэрэглэгддэг.  Мөн давталтыг таслан зогсоох боломжтой, үүнд break зааврыг ашиглаж болно.  break  ба  continue  зааврууд нь кодыг олон  гарцтай болгож унших болон засахад төвөгтэй болгодог. Тиймээс бодолтой хэрэглэх хэрэгтэй.  Доорхи  жишээ  нь  урсгалын  дохио  хянах  програм  юм.  Дохиог  гарнаас Console.ReadLine методын тусламжтай оруулна.   Алгоритм нь энгийн: “0” дохио хүлээж авбал нөхцөл хэвийн байна гэсэн үг, арга хэмжээ  авах шаардлагагүй.  Таслах  дохио “A”  хүлээн  авсан үед  боловсруулалт шууд  зогсоно.  Бусад  дохио  авсан  үед  анхааруулга  гарч  арга  хэмжээ  авахыг мэдэгдэнэ.  “X”  дохио  хүлээн  авсан  үед  анхааруулга  хийж  бөгөөд  давталт зогсоно.  using System; public class Tester { public static int Main( ) {

string signal = "0"; // initialize to neutral while (signal != "X") { // X indicates stop Console.Write("Enter a signal: "); signal = Console.ReadLine( ); // do some work here, no matter what signal you receive Console.WriteLine("Received: {0}", signal); if (signal == "A") {

// faulty - abort signal processing

Page 28: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐28‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

// Log the problem and abort. Console.WriteLine("Fault! Abort\n"); break;

}

if (signal == "0") { // normal traffic condition // log and continue on Console.WriteLine("All is well.\n"); continue;

} // Problem. Take action and then log the problem and then continue on Console.WriteLine("{0} -- raise alarm!\n",signal);

} return 0; } }  

Нэр тодорхойлох

#define DEBUG заавар нь DEBUG нэртэй препроцессорт зориулсан тогтмол утга үүсгэнэ. Мөн ийм зааврууд нь өөр кодноос using заавраар дагаж орж ирж болно.  #define DEBUG //... ердийн код – препроцессорт хамааралгүй #if DEBUG // туршилт хийх үед хөрвүүлэгдэх, ажиллах код #else // туршилт хийгээгүй үед ажиллах код #endif //... ердийн код – препроцессорт хамааралгүй  Препроцессор ажиллах үед #define зааврын дагуу DEBUG нэрийг үүсгэнэ. Дараа нь хэсэг ердийн кодыг алгасана, дараа нь #if‐#else‐#endif  блоктой таарна.   #if заавар нь DEBUG нэртэй тогтмол зарлагдсан эсэхийг шалгаж байна, ийм нэр өмнө  үүссэн  учраас  #if  ба  #else  –н  хооронд  бичигдсэн  код  програм  руу хөрвүүлэгдэнэ. Харин #else ба #endif‐н хоорондох код хөрвүүлэгдэхгүй. Ө.х энэ хоорондох код нь эцсийн ассемблай файл дотор үүсэхгүй гэсэн үг.   #if  ба #endif‐н хооронд бичигдээгүй бусад кодын хувьд препроцессорт хамаагүй бөгөөд програм руу хөрвүүлэгдэх болно.  Үүсгэсэн нэрийг #undefine заавраар хасаж болно. Жишээ нь:  #define DEBUG #if DEBUG // энэ код хөвүүлэгдэнэ #endif

Page 29: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐29‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 #undef DEBUG  #if DEBUG // энэ код хөрвүүлэгдэхгүй #endif  Эхний  #if  биелэгдэнэ,  дараагийнх  нь  биелэгдэхгүй.  (DEBUG  нэр  байхгүй болсон)  

#if, #elif, #else, #endif

Препроцессорт  олон  сонголтоос  сонгох  заавар  байхгүй,  гэхдээ  #elif,  #else заавруудаар орлуулж болно. #elif заавар нь else‐if гэсэн логиктой юм.  #if DEBUG // compile this code if debug is defined #elif TEST // compile this code if debug is not defined // but TEST is defined #else // compile this code if neither DEBUG nor TEST // is defined #endif

#region

#region  заавар  нь  тайлбар  бүхий  текст  мужийг  тодорхойлдог.  Энэ  зааврар  нь Visual  Studio  гэх  мэт  хэрэгсэл  ашиглах  үед  програмын  кодын  зарим  хэсгийг эвхэж  зөвхөн  тайлбарыг  нь  харуулахад  хэрэглэгддэг.  Жишээлбэл,  доорх жишээнд ийм кодын муж тодорхойлсон ба муж нь дэлгэгдсэн харагаж байна.  

  

Page 30: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐30‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Энд  муж  нь  #region  ба  #endregion  зааврын  хооронд  бичигдсэн  байна.  Энэ мужийг эвхсэн үед зөвхөн тайлбар нь харагдана.  

                         

Page 31: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐31‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц №4.5.6       Сэдэв: Класс ба Объектууд 

Дэд сэдвүүд:  

• Класс тодорхойлох • Объект үүсгэх • Статик гишүүд • Объектыг устгах • Параметер дамжуулах • Метод болон байгуулагчыг дахин тодорхойлох • Операторыг дахин тодорхойлох • Өгөгдлийг далдлах – Проперти  

Бид  int,  long,  char  гэх  мэт  үндсэн  төрлүүдийг  мэднэ.  Програмчлалын  хэл  нь програм  зохиогчид шинэ,  илүү  нийлмэл  төрлүүдийг  үүсгэх  боломжийг  олгох ёстой. C#‐д класс үүсгэж шинэ төрлүүдийг бий болгож болно.   Классын төлийг объект гэж хэлдэг. Програм ажиллаж байх үед объект нь санах ойд  үүсдэг.  Класс  ба  Объектын  хоорондох  ялгаа  бол  нохойны  тухай  дүрслэл, төсөөлөл ба жинхэнэ таны өмнө сууж байгаа нохой хоёрын хоорондох ялгаатай болон  ижил  зүйл юм.  Та  нохойны  дүрслэлтэй  тоглож  чадахгүй,  зөвхөн  бодит нохойтой л чадна.  Dog класс нь “нохой ямар байдаг вэ” гэдгийг тодорхойлно: жин, өндөр, нүдний өнгө, үсний өнгө  гэх мэт. Тэд мөн идэх, явах, хуцах, унтах гэх мэт хийж чаддаг авируудтай.  Тодорхой  нэг  нохой,  жишээ  нь  миний  нохой,  тодорхой  жин  (62 pounds), өндөр (22  inches), нүдний өнгө (black), үсний өнгөтэй (yellow). Тэр мөн нохойнуудын хийж чаддаг бүх л зүйлийг хийж чадна. 

  

Page 32: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐32‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 

 Объект  хандлагат прорамчлалын  том давуу  тал нь програмын  элементүүдийн боломж, шинжүүдийг нэгэн дан,  биеэ даасан нэгжид далдлан кодлох боломж олгодогт  оршдог.  Өгөгдлийн  далдлалт,  удамшил,  полиморфизм  нь  объект хандлагат програмчлалын гурван тулгуур ухагдахуун юм.   / Хуучны програм зохиогчид нэгэн хошин асуултыг тавьдаг. Объект хандлагат програм  зохиогчийн  хувьд  гэрлийг  унтраахад  хэдэн  үйлдэл  хэрэгтэй  вэ? Хариулт нь: нэг ч үйлдэл хийхгүй, зүгээр гэрлийн лампад өөрийгөө унтраа гэж хэлэхэд хангалттай. / 

3.1 Класс тодорхойлох

Классыг class түлхүүр үгээр тодорхойлно. Бичиглэл нь дараахь байдалтай:  [attributes] [access-modifiers] class identifier [:base-class ] {

class-body }  Аттрибут  болон  хандалт  тодорхойлогчийн  (access‐modifiers)  тухай  дараагийн лекцээр үзнэ. Identifier нь классын нэр юм. base‐class‐ийн тухай мөн удамшлын үед ярина. Классын биеийг муруй хаалтаар {} хашиж бичнэ.  C#‐д бүх зүйл класс дотор бичигддэг.   public class Tester {

public static int Main( ) { //... }

}  

Page 33: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐33‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Класс үүсгэх үед түүний бүх шинжүүд, авируудыг тодорхойлох ёстой.   Дараахь цаг  хадгалах,  хэвлэх  жишээнд  анхаарал  хандуулая.  Классын  дотоод  төлөв  нь одоогийн он, сар, өдөр, цаг, минут, секундыг дүрслэх чадвартай байх ёстой. Мөн энэ  класс  нь  цагыг  хэвлэн  харуулах  чадвартай  байх  хэрэгтэй.  Ийм  классыг  6 хувьсагч, 1 методтойгоор тодорхойлоё.  using System; public class Time { // public methods public void DisplayCurrentTime( ) {

Console.WriteLine("stub for DisplayCurrentTime"); } // private variables int Year; int Month; int Date; int Hour; int Minute; int Second; } public class Tester { static void Main( ) {

Time t = new Time( ); t.DisplayCurrentTime( );

} }  Энэ жишээнд Main()  метод  дотор Time  классын  объектыг  үүсгэж  t  хувьсагчид оноосон  байна.  t  нь  Time  классын  объект  учраас  DisplayCurrentTime(  )  методыг ашиглаж болно гэсэн үг.  t.DisplayCurrentTime( );  

3.1.1 Хандалт тодорхойлох

Хандалт  тодорхойлох  гэдэг  нь  тухайн  классын  гишүүн  хувьсагч,  методууд  руу ямар методууд хандаж болох вэ гэдгийг тодорхойлохыг хэлнэ.   Хандалт  Хязгаарлалт public  Хязгаарлалт байхгүй. Public гэж тэмдэглэгдсэн гишүүд рүү ямар ч метод, 

ямар ч классаас хандаж болно. private  Private  гэж  тэмдэглэгдсэн  гишүүд  рүү  зөвхөн  тухайн  классын  методууд 

хандана protected  Protected  гэж  тэмдэглэгдсэн  гишүүд  рүү  тухайн  классын  методууд  ба 

түүнээс удамшсан классын методууд хандана internal  Internal  гэж  тэмдэглэгдсэн  гишүүд  рүү  тухайн  классыг  агуулж  байгаа 

ассемблай доторх бүх классуудаас хандах боломжтой protected internal  Ассемблай  доторх  бүх  классуудаас  хандахаас  гадна  тухайн  классаас 

Page 34: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐34‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

удамшсан классын методууд хандана.   Ерөнхийдөө классын гишүүд нь private хандалттай байдаг. Гишүүний хандалтыг нь заагаагүй бол private гэж ойлгоно. Тиймээс өмнөх жишээн дэх Time классын гишүүд нь private хандалттай гэсэн үг.  private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second;  

3.1.2 Методын аргумент

Метод  нь  дурын  тооны  параметерийг  хүлээн  авдаг  байж  болно.  Методын нэрний араас параметүүдийг хаалтад жагсаан бичнэ. Жишээлбэл,  “аргумент”  ба  “параметер”  гэсэн  ойлголтуудыг  ихэнх  тохиолдолд  адилхан хэрэглэдэг,  гэхдээ  аргументыг  тодорхойлдог,  параметерыг  метод  дуудах  үед дамжуулдаг гэсэн ялгааг нь ойлгох хэрэгтэй.  void MyMethod (int firstParam, button secondParam) {

// ... }  MyMethod  метод  нь  int,  button  төрлийн  2  параметер  хүлээж  аваад  void  утга буцааж байна.  

3.2 Объект ��сгэх

Объектыг new түлхүүр үгээр санах ойд үүсгэдэг.   Time t = new Time();  Объект нь заалт төрөл юм, ө.х t нь Time объектыг яг агуулахгүй, харин санах ойд нэргүй Time төрлийн объект үүсэх ба тэр объект руу хүрэх хаягыг t агуулна.  Зураг?  

3.2.1 Байгуулагч

Дараахь Time  объектыг  үүсгэж  байгаа  бичиглэл  нь метод  дуудах  бичиглэлтэй төстэй харагдаж байна.   

Page 35: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐35‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Time t = new Time();  Үнэндээ,  объектыг үүсгэх үед метод дуудагддаг юм. Энэ дуудагдах методыг нь байгуулагч  гэж  нэрлэдэг.  Байгуулагчыг  нь  класс  дотор  тодорхойлж  өгөх  ёстой, эсвэл  CLR  үүнийг  орлуулж  хийж  өгдөг.  Байгуулагчын  үүрэг  бол  классаар заагдсан  объектыг  үүсгэх,  түүнийгээ  зөв  төлөвт  оруулах  юм.  Байгуулагч ажиллахын  өмнө  объект  нь  тодорхой  бус  санах  ойн  муж  байдаг,  байгуулагч ажилласны дараа зөв болж санах ойн муж эзэлдэг.  Байгуулагчийг  тодорхойлохдоо  классын  нэртэй  ижил  медотыг  тодорхойлдог. Байгуулагч  нь  буцаах  утгагүй  байдаг  ба  ихэнхдээ  public  хандалттай  байдаг. Хэрэв аргумент авах шаардлагатай бол аргументуудыг зааж өгөх ёстой.  Time  класс нь байгуулагч тодорхойлогдоогүй байна. Хэрэв байгуулагч байхгүй бол хөрвүүлэгч  default байгуулагчийг санал болгох ба энэ нь объектыг санах ойд үүсгэнэ,  гэхдээ  өөр  ямар  нэг  үйлдэл  хийхгүй.  Гишүүн  хувьсагчдад  нь  тогтсон (default)  утгууд  оноогдоно.  Жишээлбэл  үндсэн  төрлүүдийн  хувьд  дараахь байдалтай:  Төрөл  Тогтсон утга numeric (int, long г.м)  0 bool  false char  ‘\0’ (null) enum  0 reference  null  Time  класст  DateTime  төрлийн  нэг  параметер  хүлээн  авах  байгуулагч  нэмж бичие.  public class Time {   // public accessor methods   public void DisplayCurrentTime( ) { 

System.Console.WriteLine(ʺ{0}/{1}/{2} {3}:{4}:{5}ʺ, Month, Date,  Year, Hour, Minute, Second); 

  }   // constructor   public Time(System.DateTime dt) { 

Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second; 

  }   // private member variables   int Year;   int Month;   int Date;   int Hour; 

Page 36: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐36‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

  int Minute;   int Second; }  public class Tester {   static void Main( ) { 

System.DateTime currentTime = System.DateTime.Now; Time t = new Time(currentTime); t.DisplayCurrentTime( ); 

  } }  Энэ жишээнд  байгуулагч  нь DateTime  төрлийн  параметер  хүлээж  аваад Time объектын харгалзах гишүүн хувьсагчдад оноож байна. DateTime нь System санд байдаг  класс  юм. DateTime  классын Now  статик  гишүүн  метод  нь  системийн одоогийн цагыг өгдөг.  

3.2.2 Хуулагч байгуулагч

Хуулагч байгуулагч нь байгаа объектоос өөр нэг ижил төрлийн шинэ объектийг үүсгэдэг. Ийм байгуулагч нь объектыг хувилахад хэрэглэгдэх юм. Жишээлбэл, Time  байгуулагчид  Time  төрлийн  параметер  дамжуулж  тухайн  объектын утгуудтай ижил утгуудыг агуулах шинэ объект үүсгэх хэрэгтэй болсон гэж үзэе.   C#‐д  хуулагч  байгуулагч  байхгүй,  тиймээс  үүнийг  өөрөө  хийх  хэрэгтэй. Тухайлбал дараахь байгуулагчийг үүсгэж болно.  public Time(Time existingTimeObject) {

Year = existingTimeObject.Year; Month = existingTimeObject.Month; Date = existingTimeObject.Date; Hour = existingTimeObject.Hour; Minute = existingTimeObject.Minute; Second = existingTimeObject.Second;

} Time t3 = new Time(t2);  

Хувилах  .NET‐н  зарим  класс  Clone()  методыг  өөртөө  агуулсан  байдаг.  Энэ  метод  нь тухайн объектын яг ижил хуулбарыг санах ойд үүсгэдэг.  

3.2.3 this т�лх��р �г

this  түлхүүр үг нь тухайн объектыг өөрийг нь заана. this заалт нь классын статик биш гишүүд рүү хандах “нууц” заалт юм.  

Page 37: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐37‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 Ихэнхдээ  this  заалтыг  хэрэглэх  гурван  хэрэглээ  байдаг.  Нэгдүгээрт,  гишүүн өгөгдлийг параметерээс ялгах.  public void SomeMethod (int hour) {

this.hour = hour; }  Энэ жишээнд  SomeMethod()  метод  нь  гишүүн  хувьсагчийн  нэртэй  ижил hour  нэртэй параметерийг авч байна. Энэ үед  this заалт нь нэрсийг ялгахад туслана, this.hour  нь  гишүүн  хувьсагчийг  илэрхийлж  байна,  hour  нь  параметерийг  хэлж байна.  Хоёрдугаарт,  тухайн  объектыг  өөрийг  нь  өөр  методод  параметер  болгон дамжуулж өгөхөд ашиглана.  public void FirstMethod(OtherClass otherObject) {

otherObject.SecondMethod(this); }  Гуравдугаарт, индекслэгчид ашиглана.   

3.3 Статик гиш��д

Классын  гишүүн  нь  статик  байж  болно.  Статик  бус  гишүүдийн  хувьд  тухайн классаас  үүссэн  объекттой  холбогдсон  байдаг  бол  харин  статик  гишүүдийн хувьд  холбоогүй  байдаг.  Статик  гишүүдэд  түүнийг  агуулж  байгаа  классын нэрээр дамжуулан хандаж болно.   Жишээлбэл, Button нэртэй класс SomeMethod нэртэй статик гишүүн методтой бол   Button.SomeMethod()   гэж дуудна. Харин энэ классаас үүссэн btnUpdate гэсэн объект байх тохиолдолд   btnUpdate.SomeMethod()  гэж болохгүй. Энэ тохиолдолд хөрвүүлэгч алдаа заах болно.  Статик  гишүүд  нь  глобаль методтой  адил  гэж  ойлгож  болно,  тиймээс  объект үүсгэлгүйгээр дуудаж хэрэглэж болно. Класс дотор статик гишүүн хэрэглэхийн давуу  тал нь  тухайн  гишүүн классаараа хаяглагдана,  энэ нь  томоохон програм хангамж хөгжүүлэхэд нэрний хувьд илүү оновчтой болгож тусладаг.  Програмд  ашиглагдаж  байгаа  бүх  статик методуудыг  нэг  класс  дотор  оруулж 

Page 38: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐38‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

болох  юм.  Гэвч  энэ  нь  объект  хандлагат  загварчлалын  битүүмжлэх  чанарыг алдагдуулсан зүйл болох юм.  

3.3.1 Статик байгуулагч

Статик  байгуулагч  нь  ердийн  байгуулагчтай  төстэй,  гэхдээ  тухайн  классын объект  үүсэхээс  өмнө  дуудагддаг.  Ерөнхийдөө  классын  статик  гишүүдтэй ажиллахад  хэрэглэгддэг.  Статик  байгуулагч  нь  далд  хэлбэрийн  public хандалттай бөгөөд ханалт хувиргагч байхгүй. Статик байгуулагч нь static түлхүүр үгээр тодорхойлогдоно.  class Player { static Player() { _counter = -1; } public Player(string Name) { } }

Статик  байгуулагч  яг  хэзээ  дуудагдахыг  мэдэх  боломжгүй.  Гэхдээ  дараахь байдлаар явагдана гэдэг нь тодорхой: 

• Статик  байгуулагч  нь  классын  хамгийн  эхний  объект  үүсэхээс  өмнө дуудагдана. 

• Статик байгуулагч нь зөвхөн нэг удаа дуудагдана. • Статик байгуулагч нь статик гишүүд анхны утгаа авсны дараа дуудагдана. • Статик байгуулагч нь статик гишүүдэд хандахаас өмнө дуудагдана. 

Статик байгуулагч нь програм эхлэхэд нэг  удаа бэлдэх шаардлагатай бэлтгэл ажлуудыг хийхэд тохиромжтой.   

3.3.2 private байгуулагч

C#‐д глобаль хувьсагч, функц гэсэн ойлголт байхгүй. Тиймээс статик гишүүдийг агуулсан жижиг туслах класс үүсгэх хэрэгтэй болно. Энэ нь сайн дизайн ч бай, муу  дизайн  ч  бай  хэрэв  тийм  класс  үүсгэж  байгаа  бол  тэр  классаас  ямар  ч объект үүсгэхийг  зөвшөөрөхгүй байх  хэрэгтэй. Үүнийг private  хандалтаар  хийж болно. Ингэснээр классаас объект үүсгэх боломжгүй болно.  

3.3.3 Статик гиш��н �г�гд�лийн хэрэглээ

Статик  гишүүн  өгөгдөлийн  нэг  нийтлэг  хэрэглээ  бол  тухайн  классаас  үүсэж байгаа  объектуудыг  тоолох  юм.  Дараахь  жишээнд  instances  нэртэй  статик гишүүн  өгөгдлийг  Cat  класс  дотор  зарлаж  энэ  хувьсагчийн  эхний  утгыг  0‐ээр 

Page 39: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐39‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

оноож  байна.  Энэ  тоолуур  нь  объект  шинээр  үүсэх  бүрд  нэгээр  нэмэгдэж байна.  using System; public class Cat { public Cat( ) {

instances++; } public static void HowManyCats( ) {

Console.WriteLine("{0} cats adopted",instances); } private static int instances = 0; } public class Tester { static void Main( ) {

Cat.HowManyCats( ); Cat frisky = new Cat( ); Cat.HowManyCats( ); Cat whiskers = new Cat( ); Cat.HowManyCats( );

} } Гаралт: 0 cats adopted 1 cats adopted 2 cats adopted   Гишүүн өгөгдлийг public  хандалттай байлгах нь  тохиромжгүй юм. Энэ нь мөн статик  гишүүн  өгөгдлийн  хувьд  ч  хамаатай.  Тиймээс  статик  гишүүнийг  мөн private  хандалттай  тодорхойлох  хэрэгтэй.  Дээрх  жишээнд  instances  статик гишүүн  хувьсагчийг private  хандалттай  зарлаж,  public  хандалттай HowManyCats() статик гишүүн методыг тодорхойлсон байна.  HowManyCats() нь мөн статик учраас instances статик гишүүн рүү хандаж байна. 

3.4 Объектыг устгах

C#  нь  санах  ойн  цэвэрлэгчтэй  учраас  объектуудыг  хэрэглэж  дууссаны  дараа устгах ажлыг заавал хийх шаардлагагүй. Хэдий тийм боловч хяналтгүй   нөөц10 програмдаа ашиглаж байгаа бол ашиглаж дууссаны дараа ил хэлбэрээр устгах шаардлагатай. Үүнд зориулж Finalize() нэртэй метод хэрэглэгддэг, энэ метод нь объект устах үед үлдэгдэл цэвэрлэгчээр дуудагддаг.   

                                                 10 unmanaged resource 

Page 40: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐40‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Хэрэв  зөвхөн  хяналттай  нөөцүүд11  ашиглаж  байгаа  бол  энэ  методыг  класс дотроо хэрэглэх шаардлагагүй.   Мөн Finalize() методыг шууд дуудах хэрэггүй. Үлдэгдэл цуглуулагч үүнийг хийх болно.  

Цэвэрлэлт яаж хийгддэг вэ  Үлдэгдэл цэвэрлэгч нь Finalize() методтой бүх объектын жагсаалтыг гаргана. Энэ жагсаалт нь объект үүсэх, устах бүрд шинэчлэгдэж байдаг.   Энэ  жагсаалтад  байгаа  объект  нь  цэвэрлэгдэх  объектын  дараалалд  эхэлж бичигддэг.  Finalize()  метод  ажилласны  дараа  үлдэгдэл  цэвэрлэгч  объектыг устгана,  дараа  нь  утсгалын  дарааллаа  шинэчлэнэ,  мөн  Finalize()  хийгдэх объектын жагсаалтаа цэвэрлэнэ.  

3.4.1 Устгагч

C#‐д устгагч методыг дараахь байдлаар тодорхойлно.  ~MyClass( ) { }  Устгагч метод нь зүгээр л Finalize() методыг дуудах өөр нэг хэлбэр юм. Ө.х  ~MyClass( ) {

// do work here }  гэж бичих нь  MyClass.Finalize( ) {

// do work here base.Finalize( );

}  бичиглэлтэй  адилхан  юм.  Ер  нь  эндүүрэл  үүсгэхгүйн  тулд  устгагч  методыг ашиглахгүй  байх  нь  зүйтэй,  шаардлагатай  бол  Finalize()  методыг  ашиглах хэрэгтэй.  

3.4.2 Finalize ба Dispose

                                                 11 managed resource 

Page 41: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐41‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Finalize()  метод  нь  үлдэгдэл  цэвэрлэгчээр  дуудагдах  учраас  түүнийг  код  дотор дуудах нь хориотой. Зарим тохиолдолд үлдэгдэл цэвэрлэгчид орхилгүйгээр тэр дариуд нь  санах ойгоос цэвэрлэх хэрэг  гарна. Хэрэв хяналтгүй нөөц ашиглаад түүнийгээ  тэр  дариуд  нь  устгах  шаардлагатай  бол  IDisposable  интерфэйсийг классдаа  хэрэгжүүлэх  хэрэгтэй.  Энэ  интерфэйс  нь  Dispose()  нэртэй  методыг өөртөө агуулна. Dispose() методын утга нь  “Finalize() дуудагдахыг хүлээхгүй, шууд устга” юм.  

3.4.3 Close методыг хэрэглэх

Зарим  объектыг  устгахад  Close()  методыг  дуудах  нь  тохиромжтой  байдаг. Тухайлбал,  урсгал,  файлтай  ажиллах  объектууд  байна.  private  хандалттай Dispose() метод, public  хандалттай Close() метод  тодорхойлоод, Close()  нь Dispose()‐г дууддаг байдлаар зохион байгуулж болно.   

3.4.4 using заавар

Цэвэрлэгч  хэзээ  ажиллахыг  хянаж  чадахгүй.  Dispose()  хэзээ  дуудагдах  нь тодорхой  бус  гэсэн  үг.  Гэхдээ  C#‐д  using  зааврыг  ашиглан  тухайн  объектын амьдрах  мужийг  тодорхой  зааж,  хэзээ  устахыг  нь  хэлж  өгч  болно.  Объектын амьдрах муж нь нээх хаалтаар эхлээд хаах хаалт таарах үед автоматаар Dispose() метод дуудагдаж дуусах юм.   using System.Drawing; class Tester { public static void Main( ) {

using (Font theFont = new Font("Arial", 10.0f)) { // use theFont } // compiler will call Dispose on theFont

Font anotherFont = new Font("Courier",12.0f); using (anotherFont) { // use anotherFont } // compiler calls Dispose on anotherFont

} }  Жишээний  эхний  хэсэгт  Font  объект  using  заавартай  хамт  үүсэж  байна,  заавар дуусахад Dispose() дуудагдах болно.   Хоёр  дахь  хэсэгт  Font  объект  using  зааврын  гадна  үүсгэгдэж  байна.  Тэрхүү  Font объектыг  ашиглах  болмогц  using  заавар  дотор  оруулна,  заавар  дуусахад  мөн Dispose() дуудагдах болно.  

Page 42: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐42‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

using заавар нь мөн тооцоолоогүй алдаануудаас хамгаалдаг. Ө.х using заавар яаж ажиллаж дууссанаас үл хамааран объектыг  төгсгөлд нь  заавал устгадаг. Энэ нь try‐catch‐finally  блоктой  ижил  гэсэн  үг.  Энэ  блокын  тухай  алдаа  барих заавруудыг судлах үед ярина.  

3.5 Параметер дамжуулах

Үндсэн  төрлүүд  нь  методод  утгаараа  дамжигдана.  Метод  руу  үндсэн  төрлийн объект  дамжуулах  үед  тухайн  методод  зориулсан  түр  зуурын  хуулбар  үүсдэг гэсэн  үг. Метод  дууссаны  дараа    тэрхүү  хуулбар  нь  хаягдана. Ихэнхдээ  ингэж утгаар  дамжуулалт  хийгддэг.  Зарим  үед  заалтаар  дамжуулах  хэрэг  гардаг. Заалтаар  объектыг  дамжуулахад  ref  параметер  хувиргагчыг  хэрэглэнэ,  ref‐г анхны утга олголгүйгээр дамжуулах параметер дээр хэрэглэх бол out параметер хувиргагчыг  хэрэглэнэ.  Мөн  хувьсах  тооны  параметер  дамжуулах  үед  params параметер хувиргагчыг ашигладаг.  

3.5.1 Заалтаар дамжуулах

Метод нь нэг л объектыг буцаадаг.  Time класс дээр жишээ авая, GetTime() нэртэй цаг, минут, секунд буцаадаг метод нэмэх хэрэгтэй байг.  Энэ тохиолдолд метод нь  3  утга  буцааж  чадахгүй,  тиймээс  3  параметер  дамжуулаад  тэр  3 параметерээрээ  хүссэн  утгуудаа  буцаан  авч  болно.  Энэ  тохиололд  методыг дараахь байдлаар тодорхойлох хэрэгтэй болно.  public void GetTime(ref int h, ref int m, ref int s) {

h = Hour; m = Minute; s = Second;

}  Методын дуудалт дээр мөн өөрчлөлт хийх хэрэгтэй.  t.GetTime(ref theHour, ref theMinute, ref theSecond);  Хэрэв дамжуулахдаа ref түлхүүр үгийг орхивол хөрвүүлэгч int төрлөөс ref int төрөл рүү хөрвүүлж чадахгүй гэсэн алдаа хэлэх болно. Объектыг заалтаар дамжуулах үед  түүний  хуулбар  дамжуулагдахгүй,  харин  тухайн  объектыг  заах  заалт дамжуулагдана.  Ингэснээр  метод  тухайн  объект  дээр  ажиллана  гэсэн  үг, хуулбар дээр биш.  Энгийн үгээр хэлбэл заалтаар дамжуулна гэдэг нь “энэ объект байна, үүн дээр ажилла”, утгаар дамжуулна гэдэг нь “энэ яг адилхан хуулбар нь байна, үүн дээр ажилла” гэсэн үг юм. 

3.5.2 out параметер

Page 43: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐43‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

C#  нь  хувьсагчидыг  ашиглахын  өмнө  утга  оноосон  байхыг  шаарддаг. Жишээлбэл,  theHour,  theMinute,  theSecond  хувьсагчдыг  GetTime()  метод  руу дамжуулахын  өмнө  утга  оноохгүй  бол  хөрвүүлэгч  алдаа  хэлнэ.  Тиймээс тэдгээрт 0 анхны утгуудыг оноож өгч болно.  int theHour = 0; int theMinute = 0; int theSecond = 0; t.GetTime( ref theHour, ref theMinute, ref theSecond);  Гэвч энэ нь тухайн параметерээр дамжуулан зөвхөн буцах утга авах тохиолдолд илүү зүйл юм шиг харагдаж байна, гэвч ингэхгүй бол алдаа заана.  Use of unassigned local variable 'theHour' Use of unassigned local variable 'theMinute' Use of unassigned local variable 'theSecond'  Энэ  нөхцөлд  out  параметер  хувиргагчыг  ашиглах  нь  тохиромжтой.  out  нь параметер  заавал  эхний  утга  оноогдсон  байх  ёстой  гэсэн шаардлагыг  байхгүй болгоно. GetTime() методын зарлалтыг дараахь байдлаар засна.  public void GetTime(out int h, out int m, out int s) {

h = Hour; m = Minute; s = Second;

}  Дуудалт нь дараахь байдалтай.  t.GetTime( out theHour, out theMinute, out theSecond);  

3.6 Метод болон байгуулагчыг дахин тодорхойлох

Олон  тохиолдолд  ижил  нэртэй  нэгээс  олон  функцтэй  байх  хэрэг  гардаг. Хамгийн энгийн жишээ бол байгуулагч метод. Жишээлбэл, Time класс нь ганц DateTime  төрлийн  параметер  авах  байгуулагчтай  байна.  Time  объектыг  өөрөөр жил,  сар,  өдөр,  цаг,  минут,  секунд  параметерүүдээр  байгуулах  байгуулагч хэрэгтэй байж болно. Энэ тохиолдолд метод дахин тодорхойлолт хийгдэнэ.  Методын  таних  тэмдэг  нь  (signature)  түүний  нэр,  параметерийн  жагсаалтаар тодорхойлогддог.  Ялгаатай  нэртэй  эсвэл  ялгаатай  параметртэй  методуудыг ялгаатай таних тэмдэгтэй байна гэж хэлнэ.   void myMethod(int p1); void myMethod(int p1, int p2); void myMethod(int p1, string s1);  

Page 44: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐44‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Дээрх жишээнд бүгд ижил нэртэй метод боловч хоёр дахь метод нь эхнийхээс параметерийн  тоогоороо  ялгаатай  байна,  хоёр  дахь  нь  гурав  дахиас параметерийн төрлөөрөө ялгаатай байна.  Өмнөх жишээн дэх Time классд шинэ байгуулагч нэмэе.  public class Time { // public accessor methods public void DisplayCurrentTime( ) {

System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", Month, Date, Year, Hour, Minute, Second);

} // constructors public Time(System.DateTime dt) {

Year = dt.Year; Month = dt.Month; Date = dt.Day; Hour = dt.Hour; Minute = dt.Minute; Second = dt.Second;

} public Time(int Year, int Month, int Date,

int Hour, int Minute, int Second) { this.Year = Year; this.Month = Month; this.Date = Date; this.Hour = Hour; this.Minute = Minute; this.Second = Second;

} // private member variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second; } public class Tester { static void Main( ) {

System.DateTime currentTime = System.DateTime.Now; Time t = new Time(currentTime); t.DisplayCurrentTime( ); Time t2 = new Time(2000,11,18,11,03,30); t2.DisplayCurrentTime( );

} }   

Page 45: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐45‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Ингээд  Time  класс  нь  2  байгуулагчтай  болж  байна.  Хөрвүүлэгч  t1  объектыг байгуулах үед эхний байгуулагчыг дуудна,  t2 объектыг байгуулах үед хоёр дахь байгуулагч  методыг  дуудна  гэдгийг  мэдэх  болно.  Хүлээн  авах  параметерийн тоогоороо ялгаатай байгаа учраас.   

3.7 Операторыг дахин тодорхойлох

Өгөгдсөн төрлийн хувьд операторуудыг хэрхэн дахин тодорхойлохыг бэйсболын цохилтын  дундаж  үзүүлэлтийг  загварчилсан  жишээн  дээр  үзэе.  Бэйсболд цохилтын  үзүүлэлт  гэдэг  нь  нэг  тоглогчийн  амжилттай  цохилтын  тоог  нийт цохисон тоонд хуваасан утгыг илэрхийлнэ. 

Дараахь код нь BattingAverage төрлийн эхний хувилбар юм. 

using System; namespace MSPress.CSharpCoreRef.BattingAverageExample { public struct BattingAverage { // Constructs a new BattingAverage value type instance public BattingAverage(int atBats, int hits) { TestValid(atBats, hits); _atBats = atBats; _hits = hits; } /// Returns the batting average, subject to floating- /// point rounding public float Average() { if(_atBats == 0) return 0.0f; else return (float)_hits / (float)_atBats; } /// Tests for valid hits and at bats, throwing an exception /// if the parameters are invalid private static void TestValid(int testAtBats, int testHits){ if(testAtBats < 0) { string msg = "At bats must not be negative"; throw new ArgumentOutOfRangeException(msg); } if(testAtBats < testHits) { string msg = "Hits must not exceed at bats"; throw new ArgumentOutOfRangeException(msg); } } public int _atBats; public int _hits; } }

Page 46: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐46‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

BattingAverage  бүтэц  нь  нийт  цохилтын  тоо,  амжилттай  цохилтын  тоог илэрхийлэх  далд  гишүүн  өгөгдлүүдтэй.  Методууд  нь  цохилтын  үзүүлэлтийг шалгах, тооцоолоход хэрэглэгдэнэ. 

Ингээд BattingAverage бүтэц нь цохилтын үзүүлэлтийг   хадгалах,  тооцоолоход ашиглагдаж  болохоор  боллоо.  Хэдийгээр  эхний  хувилбар  гарсан  боловч объектуудыг харьцуулах зэрэг үйлдэл хийхэд болхи зохиомжтой болсон байна: 

if (firstBatter.Average() < secondBatter.Average()) { // secondBatter's average is higher... }

BattingAverage  классын  Average  методыг  дуудаж  үр  дүнг  нь  харьцуулахын оронд харьцуулах операторыг энэ төрөл дээр дахин тодорхойлж ердийн үндсэн төрлүүд дээрх шиг ашиглах нь тохиромжтой байна: 

if (firstBatter < secondBatter) { // secondBatter's average is higher... }

Дараагийн хувилбарт бүх шаардлагатай үйдлүүдийг дахин тодорхойлоё. 

// Equality operator for batting averages public static bool operator ==(BattingAverage left, BattingAverage right) { if((object)left == null) return false; else return left.Equals(right); } // Inequality operator for batting averages public static bool operator !=(BattingAverage left, BattingAverage right) { return !(left == right); } // Override of the Object.Equals method; returns // true if the current object is equal to another // object passed as a parameter public override bool Equals(object other) { bool result = false; if(other != null) { if((object)this == other) { result = true; } else if(other is BattingAverage) { BattingAverage otherAvg = (BattingAverage)other; result = Average() == otherAvg.Average(); } } return result; }

Page 47: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐47‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

// Converts the batting average to a string, and then // uses the string to generate the hash code public override int GetHashCode() { return ToString().GetHashCode(); } // Compares two operands using the greater than operator public static bool operator >(BattingAverage left, BattingAverage right) { return left.Average() > right.Average(); } // Compares two operands using the less than or equal to operator public static bool operator <=(BattingAverage left, BattingAverage right) { return left.Average() <= right.Average(); } // Compares two operands using the less than operator public static bool operator <(BattingAverage left, BattingAverage right) { return left.Average() < right.Average(); } // Compares two operands using the greater than or equal to operator public static bool operator >=(BattingAverage left, BattingAverage right) { return left.Average() >= right.Average(); } // Returns true if the object is logically false public static bool operator false(BattingAverage avg) { return avg.Average() == 0; } // Returns true if the object is logically true public static bool operator true(BattingAverage avg) { return avg.Average() != 0; } // Performs an AND operation on two batting averages public static BattingAverage operator &(BattingAverage left, BattingAverage right) { if(left.Average() == 0 ││ right.Average() == 0) return new BattingAverage(); else return new BattingAverage(left._atBats + right._atBats, left._hits + left._hits); } // Performs an OR operation on two batting averages public static BattingAverage operator │(BattingAverage left, BattingAverage right) { if(left.Average() != 0) return new BattingAverage(left._atBats, left._hits); else if(right.Average() != 0)

Page 48: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐48‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

return new BattingAverage(right._atBats, right._hits); else return new BattingAverage(); }

Эдгээр  харьцуулах  операторууд  нь Average  методыг  орлох  ба  BattingAverage төрлийн объектуудыг ердийн төрлүүд шиг харьцуулах боломжийг олгож байна. 

3.8 �г�гдлийг далдлах - Проперти

Проперти  нь  классын  гишүүн  өгөгдлүүд  рүү  хандах  боломж  олгодог  тусгай метод юм.   Классыг  хэрэглэгч  нь  объектын  төлвүүд  рүү  методоор  дамжуулалгүй  шууд хандахыг  хүснэ.  Класс  зохиогч  нь  классын  дотоод  төлвүүдийг  далдалж методуудаар  хандуулахыг  хүснэ.  Энэ  тохиодолд  хоёуланг  хослуулсан  шийдэл бол проперти тодорхойлох явдал юм. Энэ нь илүү төгс шийдэл юм.  Пропертиг тодорхойлохдоо түүний төрөл, нэрийг бичээд хаалтан дотор get, set хандагчдыг  тодорхойлно.  set()  метод  нь  value  түлхүүр  үгээр  далд  хэлбэрээр параметерээ хүлээн авна.  public int Hour { get {

return hour; } set {

hour = value; } }   Пропертийн  утга  болох  hour  хувьсагч  нь  өгөгдлийн  санд  хадгалагдаж  байж болно, эсвэл локаль хувьсагч байж болно.   Проперти  тодорхойлоход  get,  set  хандагчдыг  хоёуланг  заавал  тодорхойлох шаардлагагүй бөгөөд,  тухайлбал  set  хандагчыг тодорхойлоогүй тохиолдолд энэ нь зөвхөн уншигдах проперти болох юм.  Проперти  ашиглах  нь  объект‐хандлагат  загварчлалын  өгөгдлийг  далдлах шаардлагад нийцсэн оновчтой арга юм.  

3.8.1 get хандагч

get  хандагч  нь  пропертийн  төрөлтэй  ижил  төрлийн  утга  буцаадаг  методтой төстэй юм. Энэ нь пропертийн утгыг гишүүн хувьсагчийн утгаас авч буцаадаг.  

Page 49: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐49‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

get { return hour;

}  Энэ  жишээнд  локаль  int  төрлийн  хувьсагчаас  утгаа  буцааж  байна,  мөн  утгыг өгөгдлийн сангаас эсвэл  ажиллах үедээ тооцоолж гарган авч болно.  

3.8.2 set хандагч

set  хандагч  нь  пропертийн  утгыг  оноож,  void  төрлийн  утга  буцаадаг  методтой адил юм. set хандагчыг тодорхойлох үед дамжуулсан утгыг хүлээн авахдаа value түлхүүр  үгийг  ашиглана.    Пропертид  утга  оноох  үед  set  хандагч  автоматаар дуудагдагдана.   

3.9 З�вх�н уншигдах талбарууд

Классын  гишүүн  өгөгдлийг  зөвхөн  уншигдах  хандалттай  тодорхойлж  болно. Үүнийг readonly түлхүүр үгийн тусламжтай тодорхойлно.  public static readonly int Year;                         

Page 50: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐50‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц№7.8 

   Удамшил ба Полиморфизм 

Дэд сэдв��д:

• Тусгайлал ба ерөнхийлөл

• Удамшил • Полиморфизм • Хаалттай класс (sealed class) • Бүх классын үндэс Object класс • Хайрцаглах • Интерфэйс • Төрөл таних 

5.1 Тусгайлал ба Ер�нхийл�л

Классууд болон тэдгээрийн объектууд нь хоосон орчинд дангаар оршиж байдаг зүйлс  биш  юм,  тэд  бодит  амьдралд  байдаг  юмстай  адилаар  өөр  хоорондоо харилцан холбоо хамааралд оршдог.  “Is‐a” хэллэгээр илэрхийлэгдэж байгаа хамаарал бол тусгайлал (specialization) юм. Жишээлбэл,   Dog  is‐a Animal  (Нохой бол сүүн тэжээлтэн)  гэсэн хэллэг нь нохой  бол  сүүн  тэжээлтний  нэг  тусгай  төрөл  юм  гэдгийг  илэрхийлж  байна. Нохой нь сүүгээр бойждог, үстэй зэрэг сүүн тэжээлтний шинжүүдийг агуулсан байдаг,  гэхдээ  гэрийн  тэжээвэр  шинжээрээ  илүү  тусгай  юм.  Муур  мөн  сүүн тэжээлтэн амьтан. Бид муур, нохой аль алинд байдаг шинжүүдийг ерөнхийлөөд сүүн тэжээлтэн гэж хэлдэг.  Тусгайлах  ба  ерөнхийлөх  хамаарлууд  нь  гүйцээлт  ба  удамшил  юм.  Тиймээс муур  ба  нохой  нь  сүүн  тэжээлтний  тусгайлал,  сүүн  тэжээлтэн  нь  муур  ба нохойны ерөнхийлөл юм.  Эдгээр  хамаарал  нь  шаталсан  шинжтэй  байдаг.  Тусгай  шинжүүд  нь  ерөнхий шинжээсээ салаалж хамаарлын мод үүсгэдэг. Модны орой руу шилжихэд илүү ерөнхий шинжүүд  гарна. Модноос  доош шилжихэд  илүү  тусгай шинжүүдтэй болно.   

Page 51: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐51‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

  

  

UML‐ Unified Modeling Language  Энэ  номонд  классуудын  хамаарлын  диаграмыг  харуулахад  UML  хэлнээс ашигласан.  UML  (Нэгдсэн  Загварчлалын  Хэл)  нь  бизнес  болон  системийг  загварчлах стандарт  болсон  хэл  юм.  Объект  хандлагат  системийн  загварчлал  хийхэд  энэ хэл нь маш тохиромжтой байдаг.   UML  хэлэнд  классууд  нь  хайрцаг  хэлбэрээр  дүрслэгдэнэ.  Классын  нэр  нь хайрцгын дээд хэсэгт бичигдэнэ. Гишүүд нь хайрцаг дотор жагсаан бичигдэнэ. Зурагт харагдаж байгаагаар дээшээ сум нь тусгай классаас дээш илүү ерөнхий класс руу шилжиж байгааг харуулна.  

5.2 Удамшил

C# хэлэнд тусгайлах хамаарал нь ерөнхийдөө удамшилаар хэрэгждэг. Удамшил нь тусгайлах хамаарлыг илэрхийлэх цорын ганц арга зам биш юм,  гэхдээ энэ хамаарлыг илэрхийлэх хамгийн энгийн, нийтлэг арга юм.   Өмнөх жишээнд WaterAnimal ба LandAnimal классууд нь Animal классаас тусгайлан гарсан  өөрийн  гэсэн  шинжүүдтэй  класс  юм.  Суурь  классыг  ийм  аргаар тодорхойлох  нь  классуудын  олонлогт  шинэ  амьтаны  төрлүүдийг  нэмэхэд 

Page 52: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐52‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

хялбар  байх  юм.  Жишээлбэл,  Penguin  класс  нэмэхэд  WaterAnimal  классаас удамшуулж үүсгээд RentTuxedo методыг нэмэхэд л болох юм.  Удамшлыг хэрэгжүүлэхдээ дараахь байдлаар гүйцэтгэнэ.  public class Penguin : WaterAnimal  Удамшсан  класс  нь  суурь  классынхаа  бүх  гишүүдийг  өвлөн  авна,  гишүүн хувьсагчид,  гишүүн  методууд.  Удамшсан  класс  нь  суурь  классынхаа  методыг шинээр хэрэгжүүлж болно. Үүнд new түлхүүр үгийг хэрэглэнэ.   public class Penguin : WaterAnimal { // байгуулагч public Penguin() {

// ... } // SwimTo() методын шинэ хувилбар public new void SwimTo( ) {

// Penguin-ний сэлэлт } public void RentTuxedo() { // ... } }  

5.2.1 Суурь классад хандах

C#‐д  тухайн  объект  руу  this  түлхүүр  үгээр  ханддаг  бол  түүний  суурь  класс  руу base  түлхүүр  үгээр  хандах  боломжтой.  Дараахь  жишээнд  CommandWindow классын PreDraw методыг дуудаж байна:  class MyCommandWindow: CommandWindow { public void DrawShape() { base.PreDraw(); Draw(); } }

base түлхүүр үг нь зөвхөн дээд талын түвшний класс руу л хандах боломж олгоно. Өмнөх амьтадын жишээн дээр, Whale классаас base түлхүүр үгийг ашиглан Animal классын методыг дуудаж болохгүй гэсэн үг: 

class Whale : WaterAnimal { // Won't work; the following line calls a WaterAnimal // method rather than a method from Animal. base.Eat(); }

Page 53: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐53‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

base  түлхүүр  үг  нь  мөн  класс  дотор  л  бичигдэх  ёстой,  классын  гадна  хэрэглэж болохгүй: 

// Won't work; base is not allowed in this context. BessieTheCow.base.GetPlansForWorldDomination();   

5.3 Полиморфизм

Удамшилд хоёр хүчирхэг  зүйл бий: Нэг нь кодыг дахин ашиглалт. Жишээ нь, ListBox  классыг  Window  классаас  удамшуулан  үүсгэж  суурь  класс  дахь  зарим логикуудыг дахин ашиглах боломжтой.  Удамшлыг  хүчирхэг  болгож  байгаа  өөр  нэг  зүйл  нь  полиморфизм (polymorphism)  юм.  Poly  гэдэг  нь  олон, morph  гэдэг  нь  хэлбэр  гэсэн  утгатай. Тиймээс полимофирзм гэдэг нь зүйлийн олон хэлбэртэй байхыг хэлнэ.   Жишээ нь, гар утасны компани таны утас руу  дуудах дохио илгээвэл шугамын цаана  яг  ямар  төрлийн  утас  дугарахыг  мэдэхгүй.  Хуучин  загварын  мотороор хонх нь дуугардаг утас ч байж болно, эсвэл дижитал ая тоглуулах электрон утас ч байж болно.   Гар  утасны  компаны  мэдэж  байгаа  зүйл  бол  утасны  үндсэн  шинжийг  (суурь класс) мэдэх бөгөөд тухайн утас (нэг объект) яаж дугарахаа өөрөө мэднэ гэдгийг мэдэж байгаа.  Гар утасны компани таны утсанд дуугар  (ring)  гэж хэлж байгаа нь  зүгээр  л  “тохирох  зүйлээ  хий”  гэж  хэлж  байгаа юм.  Тэгэхлээр  гар  утасны компани таны утсыг полиморф болгож байна. Өөрөөр хэлбэл нэг ижил мессеж (жишээ нь, ring) өгөхөд ялгаатай хэлбэрээр хэрэгжүүлэхийг полиморфизм гэж хэлнэ.  

5.3.1 Полиморф т�р�л ��сгэх

ListBox  is‐a Window,  Button  is‐a Window  учраас  бид  эдгээр  төрлүүд  дээр  цонхны хийдэг  зүйлсийг  хийхийг  хүсэж  байгаа.  Жишээлбэл,  цонхны  эдгээр  бүх хувилбаруудыг  нэг  үндсэн  цонх  дээр  байрлуулж  түүнийг  нээгдэх  үед  бүгд зурагдсан байх шаардлагатай байг. Үндсэн цонх нь аль элемент нь ListBox, аль нь Button  гэдгийг  мэдэхгүй,  мэдэх  шаардлагагүй,  үүний  тулд  бүх  элементүүдээр гүйж бүгдэд нь “зурах” командыг л өгнө. Товчхондоо,   үндсэн цонх нь бүх цонх төрлийн объектуудыг полиморф байхыг хүснэ.  

5.3.2 Полиморф метод ��сгэх

Page 54: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐54‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Полиморфыг  дэмжих  метод  үүсгэхийн  тулд  суурь  класс  дотор  түүнийг  virtual гэж  тэмдэглэх  хэрэгтэй.  Жишээлбэл,  Window  классын  DrawWindow()  методыг полиморф гэдгийг заахын тулд дараахь байдлаар зарлана.  public virtual void DrawWindow( )  Ингээд  удамшсан  класс  бүр  өөрийн  гэсэн  DrawWindow()  методыг  хэрэгжүүлэх боломжтой  болно.  Үүний  тулд  суурь  классын  виртауль  методыг  override түлхүүр үг хэрэглэн удамшсан класс дотор дарж бичнэ.  public override void DrawWindow( ) {

base.DrawWindow( ); // invoke the base method Console.WriteLine ("Writing string to the listbox: {0}", listBoxContents);

}  Дараа нь Window, ListBox, Button төрлийн 3 объект үүсгээд тус бүрд нь DrawWindow() методыг дуудая.  Window win = new Window(1,2); ListBox lb = new ListBox(3,4,"Stand alone list box"); Button b = new Button(5,6); win.DrawWindow( ); lb.DrawWindow( ); b.DrawWindow( );  Энэ ажил нь яг хүссэнээр явагдаж бүх объектын хувьд тохирох DrawWindow() метод  ажиллах  болно.  Гэвч  энд  полиморф  хийгдээгүй  байна.  Жинхэнэ полиморф Window төрлийн массив үүсгэх үед харагдана.  Window[] winArray = new Window[3]; winArray[0] = new Window(1,2); winArray[1] = new ListBox(3,4,"List box in array"); winArray[2] = new Button(5,6);  Дээрх массивын бүх элемент дээр DrawWindow() методыг дуудах үед юу болох бол?  for (int i = 0;i < 3; i++) {

winArray[i].DrawWindow( ); }  Хэрэв DrawWindow() методыг виртуаль гэж тэмдэглээгүй бол Window классын DrawWindow()  метод  3  удаа  давтан  дуудагдах  болно.  Гэвч  виртуаль  гэж тэмдэглэсэн учраас тухайн объект бүрийн тохирох метод ажиллах болно. Энэ бол полиморфизмын гол утга санаа юм.  

Page 55: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐55‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

5.3.3 Хийсвэр метод, хийсвэр класс

Хийсвэр методын зорилго нь виртуаль методтой ижил боловч удамшсан класс тухайн  методыг  заавал  хэрэгжүүлэхийг  (implement)  шаарддагаараа  ялгаатай юм.  Виртауль методын  хувьд үүнийг  заавал шаардахгүй.  Хэрэв  хийсвэр метод нь уламшсан классаар хэрэгжээгүй бол уг классаас объект үүсгэж чадахгүй. 

abstract public void ChaseAfterBadGuys();

Хэрэв  нэг  буюу  түүнээс  дээш  тооны  класс  abstract  гэж  тэмдэглэгдсэн  бол классын тодорхойлолт мөн abstract байх ёстой. 

abstract public class Horse

Хийсвэр  классыг  хэрэгжүүлэхэд  override  түлхүүр  үгийг  ашиглан  дараахь байдлаар тодорхойлно. 

class Palomino : Horse { override public void ChaseAfterBadGuys() { } }  

5.4 Хаалттай класс (sealed class)

Хийсвэр  классын  эсрэг  хувилбар  нь  хаалттай  (sealed)  класс  юм,  ө.х  бусад классын  суурь  класс  болдоггүй.  Классыг  хаалттай  зарласнаар  хөрвүүлэгчид тухайн классыг хэзээ ч суурь класс болгон ашиглаж болохгүй гэдгийг хэлнэ.: 

sealed class Horse { }

Ердийн тохиолдолд классууд нь хаалттай бус байдаг, учир нь хаалттай класс нь цаашид  удамшуулан  өргөтгөх  боломжийг  хаадаг.  Хэдий  тийм  боловч, удамшлыг  хориглож  зөвхөн  нэг  л  классыг  тусгай  зорилгоор  үүсгэх шаардлага байж болно. Энэ нь итгэлтэй байдал эсвэл худалдааны зорилгоор шаардагдаж болно.  Классыг  хаах  өөр  нэг шалтгаан  нь  хурд,  гүйцэтгэл юм.  Хаалттай  класс ачаалагдсан үед виртауль методууд байхгүй учраас CLR  түүний методууд дээр хурдны оновчлолтууд хийж чадна. 

C# нь мөн методыг хаалттай (sealed) байхыг зөвшөөрдөг, энэ нь удамшсан класс дотор түүнийг дарж тодорхойлохоос хамгаална. 

5.5 Б�х классын �ндэс Object класс

C#  дахь  бүх  классууд  Object  классаас  удамшиж  төгсдөг.  Мэдээж  бүх  классууд шууд Object классаас удамшихгүй, гэхдээ удамшлын модыг дамжин явбал эцэст 

Page 56: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐56‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

нь Object  дээр ирэх болно. Шинээр класс үүсгэхдээ ямар нэг  удамшил  заахгүй бол  түүнийг  Object  классаас  удамшсан  гэж  ойлгодог.  Энэ  нь  дараахь  хоёр тодорхойлолт адилхан гэсэн үг: 

class Cat { } class Cat: object { }  object  төрөл  нь  .NET‐н  System.Object  класстай  ижил.  .NET  framework‐н  нэр ашигласнаас C# нэрийг нь ашигласан нь илүү дээр юм.  

C#‐н үндсэн төрлүүд мөн Object классаас удамшсан байдаг. Бүх төрлүүд нэг суурь класстай  учраас  зарим  чухал  үйлдлүүдийг  бүгд  дээр  адилхан  хийж  болно. Жишээлбэл,  C#‐н  бүх  төрлүүд  ToString()  методыг  дуудаж  тэмдэгт  мөр  рүү хялбархан хувиргалт хийгддэг: 

int n = 32; string stringValue = n.ToString()

Эсвэл утгууд дээр шууд хэрэглэж болно: 

string stringValue = 32.ToString()

Өөр методууд  мөн  байна, GetType()  нь  объектыг  санах  ойд  ажиллах  үед  ямар төрлийнх  болохыг  нь  тодорхойлно.  Мөн  үлдэгдэл  цэвэрлэгчтэй  ажиллах, тэнцүүг шалгах, хувилах методууд энэ классад байдаг. 

5.6 Хайрцаглах

 Хайрцаглалт нь үндсэн төрлүүдийг заалт төрлүүд шиг ашиглах боломж олгодог. Үндсэн  төрлийн  хувьсагчид  нь  тухайн  утгаа  дүрслэх  бит  утгуудыг  хадгалж байдаг.  Тэгвэл  яаж  заалт  төрөл  шиг  методууд  хэрэглэж  болоод  байна  вэ? Хариулт  нь  хайрцаглах  процесс  юм.  Хайрцаглалт  нь  хувьсагчийг  заалтын “хайрцаг” дотор байрлуулж заалт байдлаар ашиглах боломжтой болгодог.  

  

Page 57: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐57‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Хайрцаглалт  нь  далд  хэлбэрээр  хийгддэг,  жишээлбэл  утат  төрлийг  объектод оноох үед.   int Age = 42; object obj = Age; // Implicitly boxed  Эсрэгээрээ,  заалт  төрлөөс  үндсэн  төрөл  рүү  хөрвүүлэх  үед  ил  хэлбэрээр хөрвүүлэлт  хийх  шаардлагатай.  Үүнийг  хайрцгаас  гаргах  (unboxing)  гэж нэрлэдэг.  object obj; … int Age = (int)obj;

unboxing үйлдэлийн үед өгөгдөл алдагдах нөхцөл үүсч алдаа гарч болно.  Жишээ нь, дараахь код нь InvalidCastException алдааг үүсгэнэ: 

long feetPerLightYear; object obj = feetPerLightYear; int Age = (int)obj; // Not OK; overflows.  

5.7 Интерфэйс

Интэрфэйс нь хийсвэр классын нэг хувилбар бөгөөд классууд болон тэдгээрийн хэрэглэгчийн  хоорондох  тохиролцоог  тодорхойлдог.  Интерфэйс  бол  класс ямар байхыг хэрэглэгчид илэрхийлсэн тохиролцоо юм. Интерфэйс нь гишүүн өгөгдөл байхгүй, үйлдлийн бие байхгүй тодорхойлолт.  

5.7.1 Интерфэйсийг хэрэгж��лэх

Интерфэйсийг interface түлхүүр үгийн тусламжтайгаар тодорхойлно.  interface ISpeak { void StringToSpeech(string Message); void TextFileToSpeech(string FileName); }  Интерфэйсээс объект үүсгэж болохгүй.  // Won't work; can't be instantiated directly. ISpeak speaker = new ISpeak();

Интерфэйсийг  хэрэгжүүлсэн  класс үүсгэх  хэрэгтэй бөгөөд  тэр  классаас  объект үүсгэж болно: 

class Cat: ISpeak {

Page 58: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐58‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

} Cat anastasia = new Cat();

Энд  Cat  объектыг  ISpeak  төрлийн  объект  гэж  ярих  нь  буруу  юм,  ISpeak интерфэйсийг хэрэгжүүлсэн объект гэж хэлэх нь зөв. 

Интерфэйсийг  хэрэгжүүлж  байгаа  класс  нь  түүний  бүх  методыг  хэрэгжүүлэх үүрэгэй байдаг.   class SpeechEngine: ISpeak { public void StringToSpeech(string Message) { } // TextFileToSpeech not implemented. }

Энэ  жишээнд  SpeechEngine  класс  нь  TextFileToSpeech(  )  методыг хэрэгжүүлээгүй байгаа учраас хөрвүүлэгч алдаа заах болно. Хэрэв SpeechEngine нь  хийсвэр  класс  байсан  бол  энэ  тохиолдолд  хөрвүүлэгч  алдаа  заахгүй  байх байсан. 

Класс нь нэгээс илүү тооны интерфэйсийг хэрэгжүүлж болно. 

public class Document : IStorable, ICompressible

5.7.2 Интерфэйсийг �рг�тг�х

Шинэ метод, үйлдлүүдийг нэмэхийн тулд интерфэйсийг өргөтгөж болно. Доорх жишээнд  ICompressible  интерфэйсийг  шинэ  IloggedCompressible  интерфэйсээр өргөтгөж байна.  interface ILoggedCompressible : ICompressible {

void LogSavedBytes( ); }  

5.8 Т�р�л таних

Классууд  нь  бие  биенээсээ  удамшиж,  интерфэйс  хэрэгжүүлж  хувьсан өөрчлөгдсөн  байдаг.  Тэгвэл  нэг  объектыг  ямар  төрлийн,  ямар  классын  объект болохыг тодорхойлох шаардлага гарна.  

5.8.1 is �йлдэл

Page 59: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐59‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

is үйлдэл нь объект нь өгөгдсөн төрлийнх мөн эсэхийг шалгахад хэрэглэгддэг. Үр дүн болох утга нь логик төрөлтэй байна.  public void DisplayObject(object obj) { if(obj is BattingAverage) { // obj refers to a BattingAverage object. } }  

5.8.2 as �йлдэл

 as  үйлдэл  нь  is  ба  төрөл  хувиргах  (cast)  операторуудын  хослол  оператор  юм. Эхлээд  is  шалгалт  хийгээд  дараа  нь  төрөл  хувиргалт  хийнэ.  Хэрэв  хувиргалт амжилтгүй болвол null утга буцаана.  static void Main( ) {

Document doc = new Document("Test Document"); IStorable isDoc = doc as IStorable; if (isDoc != null)

isDoc.Read( ); else

Console.WriteLine("IStorable not supported"); ICompressible icDoc = doc as ICompressible; if (icDoc != null)

icDoc.Compress( ); else

Console.WriteLine("Compressible not supported"); }  

5.8.3 typeof �йлдэл

typeof  үйлдэл  нь  програм  ажиллах  үеийн  классын  төрлийг  тодорхойлоход хэрэглэгдэнэ.  Энэ  үйлдэл  нь  объект  бус  төрөл  дээр  хэрэглэгдэнэ.  Үр  дүн  нь System.Type төрлийн объект байна.  Type theType = typeof(BattingAverage);           

Page 60: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐60‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц№9 

Алдаа барих Дэд сэдвүүд

• Алдаа барих • Алдааны мэдээллүүдийг ашиглах • Олон алдаа баригч • finally блок • .NET Framework‐н алдааны классууд

Объект  хандлагат  програмчлалын  хэлнүүдэд  байдагтай  адилаар  C#  нь алдаанууд  болон  хэвийн  бус  нөхцөлүүдийг  алдааны  объектоор  боловсруулдаг. Алдааны  объект  гэдэг  нь  програмын  хэвийн  бус  тохиолдлуудын  тухай мэдээллийг агуулсан объект юм.  Алдааны объект (exception), алдаа (error), цоорхой (bug) гэсэн ухагдахуунуудыг ялган ойлгох нь чухал юм. Цоорхой гэдэг нь програм зохиогчийн хийсэн алдаа. Алдааны  объект  бол  цоорхойгоос  зайлах  хамгаалалт  биш  юм.  Түүнчлэн, цоорхой  нь  алдааны  объект  шидэгдэх  шалтгаан  нь  байж  болох  юм,  алдааны объектыг цоорхойгоо хянахад ашиглах ёсгүй. Харин цоорхойг  засах хэрэгтэй.  Алдаа  бол  хэрэглэгчийн  үйлдлээр  хийгдэнэ.  Жишээлбэл,  хэрэглэгч    тоо оруулах  ёстой  байтал  үсэг  оруулах.  Алдаа  нь  мөн  алдааны  объект  үүсгэх шалтгаан  байж  болох  юм.  Аль  болох  алдааг шалган  гарах  нөхцөлүүдийг  хаах хэрэгтэй.  Ингээд  бүх  алдаа  гарах  нөхцөл,  цоорхойнуудыг  хаасны  дараа  ч  програм тооцоолоогүй  асуудалд  орж  болно,  тухайлбал,  санах  ой  хэтрэх  эсвэл  файл систем  дээр  байхгүй файл  руу  хандахыг  оролдох  гэх мэт.  Алдааны  объектоос хамгаалж чадахгүй, харин програмаа бүр унагахгүйн тулд түүнийг боловсруулж болно.  Програм  санах  ой  дүүрэх  гэх  мэт  тооцоолоогүй  онцгой  тохиолдолд  ороход алдааны объектыг шиддэг. Алдааны объект шидэгдсэн үед тухайн функц тасарч түүнийг  барих  хүртэл  дээд  түвшний  функцүүд  рүү  дамжин  шидэгдэх  болно. Энэ  нь  хэрэв  тухайн  функц  алдааны  объектыг  барихгүй  бол  түүнийг  дуудсан функцэд барих боломж олдоно,  хэрэв дуудсан функцүүдээс аль нь ч барихгүй бол эцэст нь CLR –ээр баригдаж програмыг таслахад хүрнэ гэсэн үг.  

6.1 Алдааг барих

Алдааг барихын тулд алдаа гарч болох кодоо try блок дотор бичих ба гарсан үед алдааны объектыг боловсруулах кодыг catch блок дотор бичнэ. 

Page 61: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐61‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 try { Dog d; // Attempt to call through a null reference. d.ChaseCars(); } catch { // Handle any exception. }

try блок дотроос алдаа шидэгдсэн үед тухайн алдаанд тохирох алдааны объект үүсэж түүнийг барихад  тохирох catch блокоо хайдаг. Дээрх жишээнд catch блок нь  объектын  төрлийг  заагаагүй  учраас  ямар  ч  төрлийн  алдааны  объектыг барина.  Програмын  удирдлага  catch  блок  руу  шилжихэд  дараахь  арга хэмжээнүүдийг авч болно: 

• Алдааны  объектыг  боловсруулж  catch  блокын  дараагийн  кодоос програмын биелэлтийг үргэлжлүүлэх 

• Алдааны объектыг дахин шидэх 

Тусгай  алдааны  объектыг  барихын  тулд  шүүлтүүрийн  үүргээр  ажиллах параметерыг catch блокод хэрэглэж болно: 

try { Dog d; // Attempt to call through a null reference. d.ChaseCars(); } catch(NullReferenceException ex) { // Handle only null reference exceptions. }

Хэрэв  catch  блок  алдааны  объектыг  танихгүй  бол  алдааны  объект  цааш үргэлжлэн шидэгдэх  болно.  Хэрэв  catch  блок  танихгүй бол  алдааны объектыг дахин шидэх ёстой бөгөөд энэ нь өөр нэг тохирох алдаа баригчаар баригдах нь зөв юм. 

Алдааг  дахин  шидэхийн  тулд  throw  түлхүүр  үгийг  алдааны  объекттой  хамт хэрэглэнэ: 

try { Dog d; // Attempt to call through a null reference. d.ChaseCars(); } catch(NullReferenceException ex) { // (ex); Log error information. LogError (ex); // Rethrow the exception. throw(ex);

Page 62: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐62‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

}

Тухайн  алдааны  объектыг  цааш  шидэхэд  throw  түлхүүр  үгийг  параметергүй хэрэглэж болно: 

catch(NullReferenceException ex) { // Rethrow the current exception. throw; }

Алдааны  объект  дахин  шидэгдсэн  үед  түүнийг  барих  боломжтой  дараагийн catch  блок  олдох  хүртэл  хайдаг. Дуудалтын  стекийн буцах  чиглэлээр  алдааны объект  нь  цааш  шидэгдэх  бөгөөд  түүнийг  барих  хүртэл  энэ  нь  үргэлжлэнэ. Хэрэв барих код олдохгүй бол програм тасрах болно. 

6.2 Алдааны мэдээлл��дийг ашиглах

Алдааны  объектоос  ToString  методыг  хэрэглэж  алдааны  тухай  дэлгэрэнгүй мэдээллийг авч болно: 

catch(InvalidCastException badCast) { Console.WriteLine(badCast.ToString()); }

Алдааны объектод мөн бусад мэдээллүүд ч байна: 

• StackTrace  ‐ алдааны  объект  баригдсан  цэг  хүртэлх  явсан  стекийн  замыг харуулна 

• InnerException ‐  алдааны  объектыг  шидэх  явцад  нэмэгдсэн  нэмэлт объектыг буцаана 

• Message – алдааны объектыг тодорхойлсон тэмдэгт мөр • HelpLink – алдааны объектын талаар нэмэлт мэдээлэлд хүргэх URL буюу 

Universal Resource Name (URN) 

Хэрэв  програм  зохиогч  өөрийн  гэсэн  алдааны  класс  үүсгэх  бол  дээрх мэдээллүүдийг заавал багтаах хэрэгтэй..NET Framework‐н алдааны объектуудад байдагтай ижил мэдээллүүдээр хангаснаар таны класс илүү ашиглаж болохуйц байх болно. 

6.3 Олон алдаа баригч

Хэрэв  код  нэгээс  олон  төрлийн  алдааны  объект  шидэх  магадлалтай  бол тэдгээрт тохирох олон catch блок нэмэгдэх ёстой. Ямар ч төрлийн алдааг барих блокыг хэрэглэсэн үед хамгийн сүүлд байрлуулах нь зүйтэй: 

try { Dog d = (Dog)anAnimal; }

Page 63: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐63‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

catch(NullReferenceException badRef) { // Handle null references. } catch(InvalidCastException badCast) { // Handle a bad cast. } catch { // Handle any remaining type of exception. }

Ерөнхий  тохиолдолд  catch  блокуудыг  дараалуулан  байрлуулахдаа  ерөнхий шинжтэй  catch  блокуудыг  тусгай  шинжтэй  catch  блокуудын  ард  байрлуулах зарчмыг барих нь зүйтэй: 

try { Dog d = (Dog)anAnimal; } catch(Exception ex) { // Handle any exception. } catch(InvalidCastException badCast) { // Handle a bad cast. }

Энэ жишээнд эхний catch блок нь бүх төрлийн алдааны объектыг барих учраас хоёр  дахь  блок  руу  ямар  ч  алдааны  объект  дамжигдахгүй,  тиймээс  буруу хөрввүүлэлтийг  барих  кодын  хэсэг  ажиллахгүй  болно.  Энэ  нь  илэрхий  алдаа учраас хөрвүүлэгч ийм хэлбэрийн кодыг зөвшөөрөхгүй. 

Алдаа баригчуудыг үүрлүүлэн хэрэглэж болно: 

try { Animal anAnimal = GetNextAnimal(); anAnimal.Eat(); try { Dog d = (Dog)anAnimal; d.ChaseCars(); } catch(InvalidCastException badCast) { // Handle bad casts. } } catch { // General exception handling }

Алдааны  объект  үүссэн  үед  доторх  блок  ажиллана,  хэрэв  алдаа  баригдалгүй дахин шидэгдсэн бол гаднах блок түүнийг барих болно. 

6.4 finally блок

Page 64: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐64‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Метод  бичих  үед  зарим  тохиолдолд  дуудагч  руу  удирдлагыг  шилжүүлэхээс өмнө зайлшгүй хийх ёстой үйлдлүүд гардаг. Энэ нь ихэвчлэн нөөцийг чөлөөлөх, файл,  урсгалуудыг  хаах  гэх мэт үйлдлүүд байдаг. C#  ‐д үүнийг  finally  блокоор хийдэг: 

try { Horse silver = GetHorseFromBarn(); silver.Ride(); } catch { } finally { silver.Groom(); }

Энэ  жишээнд  finally  блок  нь  алдааны  объект  шидэгдсэний  дараа  ажиллана. finally  блок  нь  мөн  return,  goto,  continue,  эсвэл  break  заавруудаар  програмын удирдлагыг sөөрчилсөн ч биелэх болно. 

Энд харагдаж байгаагаар finally блок нь try блоктой залгагдсан хамт бичигдсэн байна. Хэрэв catch блок дотроос алдааны объектыг дахин шидсэн бол методын биелэлтээс гарахын өмнө эхлээд finally блок руу удирдлага шилжих болно. 

6.5 .NET Framework-н алдааны классууд

.NET  Framework  нь  маш  том  алдааны  классын  сантай.  Бүх  алдааны  класс  нь Exception классаас удамшсан байдаг ба алдааны классууд нь ямар сангаас үүсэх алдаа  гэдгээрээ  ангилагдан  тухайн  сандаа  харъяалагддаг.  Жишээлбэл,  IO классуудаас шидэгдэх алдааны классууд System.IO сан дотор байрлана. 

.NET  Framework  дэх  алдааны  классууд  нь  ихэвчлэн  шууд  System.Exception классаас  удамшсан  байдаггүй.  Харин,  төсөөтэй  алдааны  классуудаар ангилагдсан  байдаг.  Жишээлбэл,  бүх  оролт/гаралтын  алдааны  классууд  нь System.IO.IOException классын дэд классууд юм, System.IO.IOException нь өөрөө System.Exception  классаас  удамшсан.  Энэхүү  удамшлын  хамаарал  нь оролт/гаралтын  төрлийн  алдаануудыг  алдаа  бүрд  тохирсон  catch  блок бичилгүйгээр нэг блокоор барих боломжийг олгоно: 

catch(IOException ioError) { // Handle all IO exceptions here. }

Програм  зохиогч  өөрийн  алдааны  классуудыг  зохиох  үедээ  шууд System.Exception классаас удамшуулалгүйгээр энэ дүрмийг барих нь зүйтэй. 

  

Page 65: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐65‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц№ 10. 

Параллель програмчлал Дэд сэдвүүд:

• Програмын муж • Програмын зам

Бид үйлдлийн  систем нэгэн  зэрэг  хэд  хэдэн  ажил  хийж чадна  гэдгийг мэднэ. Word  дээр  юм  бичих  үед  өөр  програм  файл  татаж,  баримт  хэвлэж,  дуу тоглуулж  байдаг.  Мөн  нэг  програм  нэгэн  зэрэг  олон  ажил  хийж  байдаг. Жишээлбэл,  дууны  програм  нэгэн  зэрэг  сүлжээнээс  аудио  өгөгдөл  уншиж, түүнийгээ  задалж,  тоглуулж,  дэлгэцэн дээр  харуулж байдаг. Ийм  зүйлүүдийг хийх чадвартай програмыг параллель боловсруулалттай12  програм гэдэг.  

Параллель програмчлалд 2 үндсэн ойлголт байдаг: процесс ба зам13. Замууд бол санах ойд параллель ажиллаж байгаа биелэх кодын судлууд юм. Програм бүр ядаж  нэг  код  ажиллуулах  замтай  байна.  Програм  нь  мөн  олон  замтай  байж болно. 

Компьютерийн  систем  нь  олон  идэвхитэй  процесс,  замуудыг  агуулдаг.  Нэг процессортой  системийн  хувьд  тухайн  эгшинд  зөвхөн  нэг  л  замыг  биелүүлэх юм.  Нэг  процессортой  тохиолдолд  процессууд,  замууд  процессорыг  хуваан эзэмших ба ингэхдээ хугацаагаар хуваах14 аргыг ашигладаг. 

Одоо үед олон процессор, олон биелүүлэгчтэй компьютерүүд бий болсон. Энэ нь  параллелт  боловсруулалтын  багтаамжыг  үлэмж  нэмэгдүүлдэг.  Гэхдээ  нэг процессортой  энгийн  системийн  хувьд  ч  параллель  боловсруулалт  нь боломжтой юм.  

8.1 Програмын муж

CLR  нь  програмыг  application  domain  гэж  нэрлэгдэх  логик  процесс  дотор ажиллуулдаг. Програмын муж гэдэг нь програмын эзэмшиж байгаа хил хүрээг заагласан  тусгаарлалт юм. Програмын мужийн  тусламжтайгаар процессуудыг хянахад  хялбар  болдог.  Програм  болгон  өөрийн  мужтай  ажилладаг  бөгөөд мужууд хооронд физик процессуудыг хуваан эзэмшиж болно. 

8.2 Програмын зам

Нэг  програмын  муж  дотор  хэд  хэдэн  зам  ажиллаж  болно. System.Threading.Thread  класс  нь  програмын  зам  үүсгэхэд  зориулагдсан. 

                                                 12 concurrent 13 thread 14 Time slacing 

Page 66: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐66‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Програм  эхлэхэд  програмын  муж  нь  үндсэн  нэг  замтайгаар  эхлэнэ.  Thread классын CurrentThread пропертиг дуудаж тухайн ажиллаж байгаа замыг мэдэж болно: 

Thread currentThread = Thread.CurrentThread;

Ажиллаж  байгаа  замыг  тодорхой  хугацааны  турш  зогсооход  Sleep  статик методыг ашиглана: 

Thread.Sleep(5000);

Шинэ  зам  үүсгэхийн  тулд  эхлээд  дараахь  жишээнд  үзүүлснээр  шинэ  Thread объект үүсгэнэ: 

static void Main(string[] args) { Thread currentThread = Thread.CurrentThread; Thread workThread = new Thread(new ThreadStart(Work)); } static void Work() { Console.WriteLine("Hello"); }

Thread байгуулагч нь ThreadStart төлөөлөгчийг параметер болгон хүлээн авдаг. Замыг эхлүүлэхэд энэ төлөөлөгчийн зааж байгаа метод дуудагдаж ажиллах ба методоос гарахад замын ажиллагаа дуусна. 

ThreadStart  төлөөлөгчийн  заах  метод  нь  статик  эсвэл  статик  бус  байж  болно. Дараахь Worker классыг үүсгэе: 

public class Worker { protected string _message; public string Message { set { _message = value; } get { return _message; } } public void PrintMessage() { Console.WriteLine("Message from worker: {0}.", _message); } }

Worker  классыг  ашиглах  Thread  объект  үүсгэх  бол  Worker  объектыг  эхлээд үүсгэх хэрэгтэй: 

static void Main(string[] args){ Worker w = new Worker(); w.Message = "Hello from the worker thread"; Thread workerThread = new Thread(new ThreadStart(w.PrintMessage)); }

Page 67: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐67‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Thread объектыг үүсгэсний дараа Start методыг дуудаж замыг эхлүүлнэ: 

workerThread.Start();

Зам  нь  үйлдлийн  системээр  хянагдаж  ажиллах  ба  ThreadStart  төлөөлөгчийн метод дуусах буюу хүчээр өөр газраас зогсоох хүртэл ажиллах болно. 

Замын биелэлтийг түр зогсооход Suspend методыг хэрэглэж болно: 

workerThread.Suspend();

Хэрэв  дуудах  үед  уг  зам  эхлээгүй  эсвэл  ажиллаад  дууссан  бол ThreadStateException  алдааны  объект  шидэгдэх  болно.  Замын  тухайн  үеийн төлөвийг  ThreadState  пропертигоор  мэдэж  болно.  Дараахь  хүснэгтэд  замын төлвүүдийг харуулав. 

Төлөв  Тайлбар Aborted  Замыг тасалсан AbortRequested  Өөр замаас тухайн замыг таслах хүсэлт ирсэн 

Background Зам  нь  ард  ажиллах  зам  (background  thread) байдлаар ажиллаж байна 

Running  Зам ажиллаж байна Stopped  Замын ажиллагаа зогссон StopRequested  Зам зогсох хүсэлт илгээсэн Suspended  Зам түр зогссон SuspendRequested  Түр зогсоох хүсэлт илгээсэн Unstarted  Зам үүссэн, гэхдээ эхлээгүй 

WaitSleepJoin Зам  түгжигдсэн  эсвэл  түр  зогссон  эсвэл  өөр  зам холбогдохыг хүлээж байна 

Дээрх хүснэгт дэх төлвүүд нь ихэвчлэн хосолж хэрэглэгддэг.                  

Page 68: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐68‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

ЛЕКЦ№11      ЦОНХТОЙ ПРОГРАМ  

Цонхнууд 

Дэд сэдвүүд: • Цонхны хэлбэрүүд • Цонхтой програм үүсгэх • Clipboard • Drag and Drop  

Windows  програмчлалын  эхэн  үед  програмууд  тусдаа  компьютерүүд  дээр ажилладаг  байсан.  Цаг  хугацаа  өнгөрөхөд  програм  зохиогчид  хэрэглэгчийн интерфэйстэй  хэсэг  нь  тусдаа нэг  компьютер дээр,  өгөгдлийн  сантай  хэсэг  нь өөр нэг компьютер дээр сүлжээгээр холбогдон ажиллах нь илүү давуу талтай юм  байна  гэдгийг  олж  мэдсэн.  Програмыг  ингэж  үүргийн  хувьд  тусгаарлаж байгааг  2‐давхаргат  (two‐tier)  буюу  клиент/сервер  хөгжүүлэлт  гэж  нэрлэсэн байна.  Сүүлд  энэ  нь  3‐давхаргат  эсвэл  n‐давхаргат  зэргээр  нэрлэгдэж  вэб үйлчилгээнүүдийг ашиглаж эхэлсэн.  Хамгийн  анхны  Вэб  програм  гарч  ирэх  үед  Windows  програм  болон  Web програмын  хооронд  тодорхой  ялгаа  зааг  бий  болсон.  Windows  програм  нь десктоп эсвэл локаль сүлжээнд ажиллана, Web програм нь алсын сервер дээр ажиллах ба браузерээр хандана.  Энэ  ялгаа  одоо  улам  арилж  байна.  Одоо Windows  ба Web  програмыг  ялгах үндсэн  ялгаа  бол  хэрэглэгчийн  интерфэйсийг  хэн  эзэмшиж  байна  гэдгээр ялгагдаж  байна.  Програмын  хэрэглэгчийн  интерфэйсийг  харуулахад  браузер ашиглаж  байна  уу?  Эсвэл  график  интерфэйс  дээр  тулгуурласан  биелэх програм уу?  Миний бодлоор Windows ба Web програмын хооронд байгаа энэ ялгаа нь түр  зуурын  юм.  Дараагийн  үеийн  хөгжүүлэлтийн  хэрэгслүүд  дээр  энэ ялгаа байхгүй болно гэдэгт итгэлтэй байна.  Windows  програмууд  хийхэд  Windows  Forms  ‐ыг  ашигладаг,  Web  програм хийхэд Web Forms‐ыг ашигладаг.  System.Windows.Forms  сан  нь  цонхтой  хэрэглэгчийн  интерфэйс  бүхий програмуудыг зохиоход зориулагдсан баялаг сан юм. Энэ сан дахь Form класс нь бүх төрлийн диалог, цонх классуудын суурь класс нь юм.  

1.1 Цонхны хэлбэрүүд  

Page 69: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐69‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Form‐г  ашиглах  хамгийн  энгийн  хэрэглээ  нь  хэрэглэгчтэй  харилцан  ажиллах диалог цонх юм. Диалоги цонх нь ердийн текст агуулсан энгийнээс эхлээд олон тооны контрол агуулсан нийлмэл хүртэл байдаг.  Зарим диалоги цонхнууд үйлдлийн системийн нэг хэсэг болж багтсан байдаг. Ийм  диалоги  цонхнуудыг  үндсэн  диалоги  цонх  (common  dialog  box)    гэж нэрлэдэг, энд жишээлбэл, өнгө сонгох, фонт сонгох, принтерийн тохиргоо хийх гэх мэт цонхуудыг нэрлэж болно.  Диалоги  цонхууд  нь  ихэнхи  тохиолдолд  хэрэглэгчид  мэдээлэл  хийхэд хэрэглэгддэг. Үүнд зориулж мессежийн цонхыг ашигладаг.  .NET‐д MessageBox классыг ашиглан ийм хэлбэрийн цонхыг харуулж болно.  Ердийн  цонхтой  програм  нь  нэгээс  олон  тоонын  цонхуудтай  ажилладаг,  мөн хүү цонхуудтай байж болно. Цонхыг харуулахдаа 2 хэлбэрээр харуулж болно.  

• Модаль  цонх    (modal  form)  –  ийм  цонх  нээгдсэн  үед  програмын  бусад хэсгүүдтэй  ажиллах  боломжгүй  болно.  Ийм  хэлбэрийн  цонх  нь програмыг  цааш  үргэлжлүүлэхэд  шаардлагатай  мэдээллийг хэрэглэгчээс асуухад тохиромжтой. 

• Ердийн цонх (modeless  form) – ийм цонх нээгдсэн үед програмын бусад хэсгүүдтэй  ажиллах  боломжтой.  Ийм  хэлбэрийн  цонх  нь  удаан хугацааны туршид ашиглахад тохиромжтой. 

 Модаль цонхны жишээнүүд бол алдааны мэдээлэл харуулах мессежний цонх, файл нээх, хадгалах диалоги цонхнууд юм. Ердийн цонхны жишээнд хэрэглэгч ажиллах  боломж  бүхий Microsoft Word  програмын  хүү  цонхнуудыг  нэрлэж болно. Ихэнхи тохиолдолд модаль бус цонхуудыг програмд ашигладаг бөгөөд хэрэглэгчээс  лавлаж  байж програм цааш үргэлжлэх шаардлагатай  хэсгүүдэд модаль цонхуудыг ашиглах нь тохиромжтой юм. 

1.1.1 Модаль ба модаль бус цонх  Цонхыг модаль эсвэл модаль бус хэлбэр нь түүнийг яаж харуулснаас хамаарна. Ердийн цонх харуулахад Show методыг дараахь байдлаар хэрэглэнэ.  Form addressForm = new AddressForm(); addressForm.Show(); 

Цонхыг програмын замаар хаахдаа Close методыг хэрэглэж болно: 

addressForm.Close(); 

Мөн өөр нэг хэлбэр нь Hide методыг ашиглан харагдахгүй болгож болно: 

Page 70: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐70‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

addressForm.Hide(); 

Модаль цонх харуулахын тулд ShowDialog методыг ашиглана: 

addressForm.ShowDialog();  ShowDialog методын дуудалт нь хэрэглэгчээс хариу өгөх хүртэл дуусахгүй. Диалоги цонхноос хэрэглэгч ямар сонголт хийснийг DialogResult тогтмолуудын тусламжтай таньж болно.  Form addressForm = new AddressForm(); DialogResult result = addressForm.ShowDialog(); if(result == DialogResult.OK) {     // Dialog box contents are valid. } 

DialogResult тоочих төрөл нь дараахь тогтмол утгуудыг агуулна: 

• Abort • Cancel • Ignore • No • None • OK • Retry • Yes 

Энэ  буцах  утга  нь  ихэвчлэн  хэрэглэгчийн  дарсан  товчны  утга  байх  юм. Жишээлбэл,  хэрэглэгч  Esc  товч  дарсан  бол  DialogResult.Cancel  утга  буцаах болно.  

1.1.2 Мессеж цонх  Мессеж цонхыг харуулахдаа MessageBox классын Show методыг ашиглана.  MessageBox.Show(ʺA simple message boxʺ); 

Show  методын  дээрх  хувилбар  нь  хамгийн  энгийн  мессеж  цонхыг  харуулна, параметерээр дамжуулсан текст ба OK товчлуур.  

 

Page 71: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐71‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Илүү  олон  боломжууд,  товчнууд,  зургуудыг  харуулж  чадах  Show  методын  12 янзын хувилбар байдаг. 

Мессеж  цонхонд  гарчиг  хийхийн  тулд  хоёр  дахь  параметерыг  нэмж  дараахь байдлаар хэрэглэнэ: 

MessageBox.Show(ʺA simple message boxʺ, ʺMessageBox demoʺ); 

Мессеж  цонх  нь  OK  товчноос  өөр  олон  товчнуудтай  байж  болно,  энэ  нь хэрэглэгчээс олон төрлийн хариулт авах боломж олгоно. Мессеж цонхон дээр 3 хүртэлх  товч  байж  болно,  эдгээр  товчнуудыг  өөрөө  үүсгэх  шаардлагагүй MessageBoxButtons тоочих төрөлд заасан утгуудыг ашиглана. 

• AbortRetryIgnore ‐ Abort, Retry, Ignore товчнууд • OK – Ok • OKCancel – Ok, Cancel • RetryCancel – Retry, Cancel • YesNo – Yes, No • YesNoCancel – Yes, No, Cancel 

Дараахь кодонд олон сонголттой мессеж цонхыг харуулж байна: 

DialogResult result = MessageBox.Show(ʺA message box with 3 buttonsʺ,                                       ʺMessageBox demoʺ,                                       MessageBoxButtons.YesNoCancel); switch(result) {      } 

MessageBoxIcon  тоочих  төрөл  нь мессеж  цонхонд  дүрслэгдэх  зургуудын  (icon) олонлогыг агуулна.  

Гишүүн  Тайлбар 

Asterisk  

Error  

Exclamation  

Hand  Error‐той адил. Information  Asterisk‐тай адил. None  Icon дүрслэгдэхгүй. 

Question  

Stop  Error‐той адил Warning  Exclamation‐тэй адил 

Мессеж цонхыг дээрх icon‐уудтай харуулахад дараахь байдлаар хэрэглэнэ: 

Page 72: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐72‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

DialogResult result = MessageBox.Show(ʺA message box with an iconʺ,                                       ʺMessageBox demoʺ,                                       MessageBoxButtons.YesNoCancel,                                       MessageBoxIcon.Asterisk); switch(result) {      }  

1.1.3 SDI, MDI 

 1.2 Цонхтой програм үүсгэх  Application  класс  нь  цонхтой  програмуудыг  удирдахад  хэрэглэгдэнэ. Програмыг  эхлүүлэх,  дуусгах  зэрэгт  уг  классын  Run,  Exit  зэрэг  статик методуудыг хэрэглэнэ.  Жишээлбэл,  Run  методыг  ашиглан  програмыг  дараахь  байдлаар  эхлүүлж болно.  Application.Run(new Form1()); 

Run методын 3  хувилбар байдаг. Дээрх жишээнд хамгийн өргөн хэрэглэгддэг хувилбарыг  харуулсан  байна.  Run  метод  нь  мэдэгдэл  боловсруулагчийг (message  loop)  эхлүүлж  параметер  болгон  дамжуулсан  цонхыг  харуулна. Microsoft  Visual  Studio  .NET  –ээр  Windows  Forms  project  үүсгэх  үед  Run методын энэ хувилбарыг ашигладаг. 

Мөн өөрөөр, Run методыг параметергүйгээр дуудаж болно: 

Application.Run(); 

Run  методыг  параметергүй  дуудсан  үед  мэдэгдэл  боловсруулах  процессийг эхлүүлэх боловч цонх харуулахгүй. Run методын энэ хувилбар нь цонхоо сүүлд харуулахад зарим тохиолдолд хэрэгтэй байдаг. 

Run  методын  гуравдахь  хувилбар  нь  ApplicationContext  объект  хүлээн  авдаг. Run  методын  өмнөх  хувилбаруудад  ApplicationContext  мөн  далд  ашиглагдах бөгөөд  үндсэн  цонхыг  хаах  үед  програмыг  автоматаар  хаах  зэрэг  үүргийг гүйцэтгэдэг. Програм зохиогч ApplicationContext классаас удамшуулан өөрийн тусгай  шинж  бүхий  хувилбарыг  үүсгэж  болно.  Дараахь  жишээнд ApplicationContext  классаас  удамшсан,  програмыг  хаах  шинжийг  өөрчилсөн шинэ класс үүсгэсэн байна: 

public class QueryApplicationContext: ApplicationContext {     private string _saveMessage = ʺExit and discard changes?ʺ;     private string _caption = ʺApplication Exitʺ; 

Page 73: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐73‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

     public QueryApplicationContext(MainForm form) {         form.Show();         form.Closing += new CancelEventHandler(FormClosing);     }      private void FormClosing(object sender, CancelEventArgs e) {         DialogResult result = MessageBox.Show(saveMessage,                                        _caption,                                        MessageBoxButtons.YesNo,                                        MessageBoxIcon.Question,                                        MessageBoxDefaultButton.Button1);         if(result == DialogResult.Yes) {             ExitThread();         }         else {             e.Cancel = true;         }     } } 

Энэ  жишээнд  FormClosing  метод  нь  програмын  үндсэн  цонхны  Closing үзэгдлийг  боловсруулж  байна. Closing  үзэгдэл  нь  цонх  хаагдах  үед  үүсдэг  ба CancelEventArgs  объектыг  параметер  болгон  дамжуулдаг.  FormClosing  метод дотор  хэрэглэгчээс  лавлагаа  асуусан  мэдэгдлийн  цонх  харуулж  байна. Хэрэглэгч Yes товч дарсан бол ExitThread дуудагдаж програмыг таслана, хэрэв No дарсан бол Closing үзэгдэл цуцлагдах болно. 

Энэ  классаа  ашиглахын  тулд  түүнээс  объект  үүсгэж Application.Run  методод дараахь хэлбэрээр дамжуулна: 

static void Main() {     MainForm form = new MainForm();     QueryApplicationContext appContext;     appContext = new QueryApplicationContext(form);     Application.Run(appContext); }  1.2.1 Програмын замыг тодорхойлох 

Програмд  шаардлагатай  файлуудыг  байрлуулах  үед  түүний  замыг  мэдэх шаардлага  гардаг. Application  класс  нь  програмын  зам,  програмын  өгөгдлийг хадгалсан  хавтасуудын  мэдээллийг  тодорхойлоход  ашиглагдах  методуудыг агуулна. 

Програм  ачаалагдсан  байрлалыг  тодорхойлоход  ExecutablePath  пропертиг ашиглана: 

string executablePath = Application.ExecutablePath; 

Page 74: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐74‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Програм эхэлсэн хавтасын байрлалыг авахад StartupPath проперти ашиглана: 

string startupPath = Application.StartupPath; 

Windows  програмуудын  хувьд  өгөгдөл  нь  хандахад  хялбар  байхаар  тусгай байрлалд байдаг. Програмын өгөгдөл нь Documents And Settings  хавтасын дэд хавтас  болон байрлах  ёстой  (Documents And Settings\<user_name>). Өгөгдлийг ийм  байдлаар  хадгалах  нь  нэг  байрлалаас  бүх  өгөгдөлдөө  хүрэх  боломжийг олгоно. Application класс нь эдгээр замыг тооцоолоход туслана. 

Нийтийн хавтасыг тодорхойлоход CommonAppDataPath пропертиг ашиглана: 

string commonDataPath = Application.CommonAppDataPath; 

Зам  нь  Documents  And  Settings\All  Users\Application  Data    хавтас  дотор <company_name>\<product_name>\<version>  дэд  хавтас  хэлбэрээр  олдоно. Компани  болон  бүтээгдэхүүний  нэр  зэрэг  мэдээллийг AssemblyInfo.cs  файл дотор програм зохиогч зааж өгнө. 

Тусгай  хэрэглэгчийн  хавтасыг  тодохойлоход  UserAppDataPath  пропертиг ашиглана: 

string userDataPath = Application.UserAppDataPath;  

Энэ  зам  нь  нийтийн  замтай  ижил  дүрмээр  байрлах  ба  ялгаа  нь  тусгай  нэг хэрэглэгчийн  мэдээлэлд  хүрэхэд  зориулагдсан.  Жишээлбэл,  Ali  нэртэй хэрэглэгчийн хувьд програмын өгөгдөл Documents And Settings\Ali\Application Data хавтас дотор байрлана. 

1.2.2 Сул зогсолт 

Мэдэгдэл  болвсруулагч  ямар  нэг  ажил  гүйцэтгэлгүй  сул  зогссон  үед  Idle  гэж нэрлэгдэх  тусгай  үзэгдэл  үүсдэг,  энэ  үед  доогуур‐зэрэглэлтэй  (low‐priority)  ажлуудыг  гүйцэтгэх  боломж  бүрдэнэ.  Тухайлбал,  Idle  үзэгдэл  үүссэн  үед төлвийн  мөр  зэрэг  хэрэглэгчийн  интерфэйсийн  хэсгүүдийг  шинэчлэх ажлуудыг хийж болно. 

Idle  үзэгдлийг  боловсруулах  EventHandler  төрлийн  метод  тодорхойлох хэрэгтэй: 

private void OnIdle(object sender, EventArgs e) {     // Perform idle processing here. } 

Idle  үзэгдлийг  барих  захиалга  хийхийн  тулд  дээрх  методыг  Application.Idle үзэгдэл баригчид нэмэх хэрэгтэй: 

MyForm() { 

Page 75: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐75‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

    Application.Idle += new EventHandler(OnIdle); }  1.2.3 Програмыг дуусгах 

Анхны төлөвөөрөө үндсэн цонхыг хаахад програмын ажиллагаа дуусдаг. Өмнө дурдсанаар мөн ApplicationContext классаар энэ шинжийг өөрчилж болно. Өөр нэг арга зам бол Application классыг шууд ашиглаж болно. 

Application класс нь програмыг дуусгах мэдэгдэлийг өгөх Exit методыг агуулна. Exit метод нь ямар ч thread ‐ээс дуудагдаж болно: 

Application.Exit(); 

Exit метод нь програмыг шууд дуусгах метод биш юм, энэ метод дуудагдсан үед бүх  мэдэгдэлүүд  хаагдаж  Run  метод  дуусах  юм.  Run  метод  дуусах  нь програмын ажиллагаа дуусахтай адил бөгөөд зарим тохиолдолд түүний дараа програмд ашиглагдсан нөөцүүдийг цэвэрлэх кодууд байж болдог. 

static void Main() {     Application.Run(new Form1());     appMutex.Close();     stream.Close(); } 

Ерөнхийдөө Exit методыг шууд дуудах хэрэггүй, учир нь энэ нь нээлттэй байгаа цонхуудыг шууд хаадаг. Цонхтой програмыг дуусгах хамгийн оновчтой арга бол үндсэн цонхны Close методыг дуудах юм. 

Програмын тодорхой замыг дуусгахад ExitThread методыг ашиглана: 

if (Application.MessageLoop == true)     Application.ExitThread(); 

Энд MessageLoop проперти нь тухайн  thread‐д мэдэгдэл боловсруулалт бйагаа эсэхийг шалгана. 

Програм  дуусаж  байгааг  мэдэхийн  тулд  ApplicationExit  үзэгдэлийг  захиалах хэрэгтэй.  Дараахь  жишээнд  энэ  үзэгдлийг  ашиглан  програмд  хэрэглэгдсэн нөөцүүдийг цэвэрлэж байна: 

// Байгуулагч AddressForm() {     // ApplicationExit үзэгдэлийг OnAppExit функцээр барих захиалга      Application.ApplicationExit += new EventHandler(OnAppExit); }  private void OnAppExit(object sender, EventArgs e) {     appMutex.Close(); 

Page 76: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐76‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

    stream.Close(); }  

1.3 Clipboard 

1.4 Drag and Drop 

            Лекц№12,13 

Контролууд  Дэд сэдвүүд: 

• Button • TextBox • Label • LinkLabel • ListBox • CheckedListBox • ComboBox • ScrollBar • Агуулагч элементүүд • StatusBar • ProgressBar • PictureBox • TabControl • Toolbar • TreeView 

 Цонхтой  програмд  маш  олон  төрлийн  контролууд  ашиглагддаг.  Зарим контролууд нь нийлмэл,  tree view,  list view  гэх мэт,  зарим нь  энгийн,   button, status bar зэрэг.   2.1 Button  Button,  RadionButton,  CheckBox  классууд  нь  товчлуур  ангиллын  классд хамаарна.  Эдгээр  классууд  ButtonBase  нэртэй  нэг  классаас  удамшсан  бөгөөд Windows‐н стандарт товчнуудыг дүрслэхэд хэрэглэгддэг.  

Page 77: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐77‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Button ангиллын классуудын нийтлэг шинжүүд нь: • Дарагдаж болно (click) • Гарчигтай (label) 

Button  класс  нь  товчлуур  контролыг  дүрслэх  ба  товчлууртай  ажиллах үйлдлүүдийг  хялбарчилсан  үзэгдэл,  методуудыг  агуулдаг.  Button  класс  нь товчлуурын  үзэгдэх  байдлыг  удирдах  пропертинуудыг  агуулдаг.  Дараахь пропертинуууд хамгийн их хэрэглэгддэг: 

• FlatStyle  ‐ контролын ирмэг яаж зурагдахыг заана • BackColor  ‐ контролын дэвсгэр өнгийг заана • ForeColor – контролын текстийн өнгө • Text  ‐ контролд дүрслэгдэх текст 

FlatStyle проперти нь дараахь утгуудыг авч болно. 

Утга  Тайлбар Flat  Хавтгай товч Popup  Товчлуур ердийн үед хавтгай боловч хулгана дээгүүр нь гүйх үед 

төвгөр болно Standart  3 хэмжээст ирмэгтэй товчлуур System  Товчлуурын хэв маяг нь үйлдлийн системээр тодорхойлогдоно 

 

 

Бусад  пропертийн  адилаар  FlatStyle  пропертиг  проперти  цонхон  дээрээс өөрчилж болохоос гадна програмын аргаар өөрчилж болно.  

closeButton.FlatStyle = FlatStyle.Flat; 

Зарим  тохиолдолд  товчлуурын  гарчигыг  солих шаардлага  гарна. Жишээлбэл, шинэ  цонх  нээдэг  товчлуур  “Нээх”  гэсэн  гарчигтай  байг.  Цонх  нээгдсэний дараа уг товчлуурын гарчигыг “Хаах” гэж солих нь зүйтэй: 

private void ToggleWindow() {     if(openButton.Text == ʺOpen Windowʺ) {         reservationForm = new ReservationForm();         reservationForm.Show(); 

Page 78: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐78‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

        openButton.Text = ʺClose Windowʺ;     }     else {         reservationForm.Close();         openButton.Text = ʺOpen Windowʺ;     } } 

Энэ  жишээнд  харуулснаар  Text  пропертийн  тусламжтайгаар  контролын гарчигийг  сольж  байна.  Бүх  цонх,  контролууд  гарчиг,  шошгыг  нь  өөрчлөх боломж  олгох  Text  пропертитэй  байдаг.  Товчлуурыг  гарны  тусламжтайгаар сонгох  боломж  олгохын  тулд  гарчигийн  нэг  тэмдэгтийн  өмнө  амперсанд  (&) хэрэглэнэ: 

openButton.Text = ʺ&Close Windowʺ; 

Амперсанд  өмнө  нь  тавьсан  тэмдэгт  ба  ALT  товчны  хослолоор  тухайн товчлуурыг сонгож болно. 

RadioButton  контрол нь хэд хэдэн сонголтоос нэгийг нь сонгоход ашиглагддаг. Нэг  цонхон  дээр  олон  radio  button  байх  үед  хэрэглэгч  нэгийг  нь  сонгоход үлдсэн  бусдыг  нь  сонгоогүй  төлөвт  оруулдаг.   Checked  проперти  нь  товчлуур сонгогдсон эсэхийг мэдэх болон сонгоход ашиглагдана.   if(standardRadio.Checked == true) { }   standardRadio.Checked = false;  CheckBox нь олон сонголтоос хэд хэдэн сонголт хийх боломж олгоно.  2.2 TextBox  TextBox  контрол  нь  текст  оруулах,  засах  үндсэн  контрол  юм.    Зарим  чухал пропертиг дараахь хүснэгтэд үзүүлэв.  Проперти  Тайлбар Text  Контролд оруулсан текстийг авах, солих Clear  Контрол доторхи текстийг цэвэрлэх PasswordChar  Хэрэглэгчийн оруулж байгаа текстийг нууцлах шаардлагатай 

үед хэрэглэнэ. Өгөгдсөн тэмдэгтээр хэрэглэгчийн оруулж буй тэмдэгт солигдож бичигдэнэ 

Multiline  Олон мөр тэмдэгт мөр оруулах боломж олгоно WordWrap  Текстийг контролын өргөнтэй тэгшилж цэгцлэнэ AcceptsReturn  Энэ проперти  true  утга  авсан  үед Enter  товч  дарж шинэ мөр 

оруулахыг зөвшөөрнө. Эсрэг тохиолдолд Enter товч дарсан үед 

Page 79: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐79‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

цонхны үндсэн товчлуурыг (default button) сонгох болно AcceptsTab  Энэ  проперти  true  утга  авсан  үед  Tab  товч  дарж  зай  авахыг 

зөвшөөрнө. Эсрэг тохиолдолд Tab  товч дарсан үед дараагийн контролыг сонгох болно 

BorderStyle  Товчлуурын үзэгдэх хэлбэрийг өөрчлөнө  2.3 Label  Label  контрол  нь  цонх  дээр  тодорхойлолт,  гарчиг  текстүүдийг  байрлуулахад хэрэглэнэ.  Энэ  контрол  нь  ерөнхийдөө  TextBox  зэрэг  өөрийн  гарчиг  байхгүй контролуудыг нэрлэх зорилгоор хамт хэрэглэгддэг.  2.4 LinkLabel 

LinkLabel  нь  вэб  хуудас  дээрх  шиг  холбоосыг  дүрслэнэ.  LinkLabel  класс  нь HTML  холбоостой ижил шинжүүдийг агуулсан байдаг.  Тухайлбал,  холбоосын төлвөөс  хамааруулан  өөр  өнгөөр  дүрсэлж  болно.  Холбоосын  өнгийг тодорхойлоход дараахь пропертинуудыг ашиглаж болно: 

• ActiveLinkColor – холбоосын сонгогдох үеийн өнгө • DisabledLinkColor  ‐ холбоосын идэвхгүй үеийн өнгө • LinkColor  ‐ холбоосын ердийн үеийн өнгө • VisitedLinkColor – холбоосын зочилсоны дараахь өнгө 

LinkLabel  объектоор  ашиглагдах  өнгүүд  нь  Properties  цонх  эсвэл  програмын аргаар тогтоогдож болно: 

public WebLookForm() {     linkLabel.ActiveLinkColor = Color.Lime;     linkLabel.DisabledLinkColor = Color.DarkOrange;     linkLabel.LinkColor = Color.DarkGreen;     linkLabel.VisitedLinkColor = Color.DarkOliveGreen; }  Анхны  өнгүүд  нь  LinkColor  =  Color.Blue,  ActiveLinkColor  =  Color.Red,  VisitedLinkColor  = Color.Purple байдаг.  2.5 ListBox  

ListBox  контрол  нь  элементүүдийн  жагсаалтыг  дүрслэнэ.  Жагсаалт  дахь элементүүдэд хандахад дараахь классуудтай ажилладаг: 

• ListBox.ObjectCollection  ‐ жагсаалт дахь бүх объектууд • ListBox.SelectedIndex –  жагсаалт  дахь  сонгогдсон  элементүүдийн индексүүд 

Page 80: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐80‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

• ListBox.SelectedObjectCollection ‐  жагсаалт дахь сонгогдсон элементүүд 

Энэ  классуудаас  хамгийн  их  хэрэглэгддэг  нь  ListBox.ObjectCollection  юм. Жагсаалт  дахь  элементүүдийг  гарган  авахад  Items  пропериг  дараахь  байдлаар ашиглана: 

private void RemoveItems(ListBox listBox) {     ListBox.ObjectCollection items = listBox.Items;     if(items.Count != 0) {               } } 

Ерөнхийдөө,  ObjectCollection  төрлийн  заалт  ашиглалгүйгээр  шууд  Items проперти дээр ажиллах нь хялбар юм: 

private void RemoveItems(ListBox listBox){     if(listBox.Items.Count != 0) {               } }  ListBox.ObjectCollection  классын  зарим  чухал  методуудыг  дараахь  хүснэгтэд үзүүлэв.  Метод/проперти  Тайлбар Add  Жагсаалтад элемент нэмэх Insert  Жагсалтад элемент оруулах AddRange  Жагсаалтад  элементийн  олонлог 

нэмэх RemoveAt  Өгөгдсөн  индекс  дээрх  элементийг 

устгах Remove  Өгөгдсөн элементийг устгах Clear  Жагсаалтыг цэвэрлэх  ListBox  класс  нь  жагсаалт  контролтой  ажиллах  олон  чухал  пропертинуудыг агуулна. 

• MultiColumn ‐ олон багана элементүүдийг дүрслэх боломж олгоно • ColumnWidth – олон баганатай үед баганын өргөнийг заана • SelectionMode ‐ жагсаалт дахь элементүүд яаж сонгогдохыг заана • Sorted  ‐ элементүүдийг автоматаар эрэмбэлнэ • TopIndex – жагсаалт дахь хамгийн дээр харагдах элементийг заана 

2.5.1 ListBox‐г дахин зуралтаас хамгаалах 

Page 81: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐81‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 Жагсаалтад  элемент  нэмэгдэх,  хасагдах  бүрт  контрол  дахин  зурагдаж  байдаг. Олон  элементийг  нэг  үйлдлээр  зэрэг  нэмэх  хамгийн  зөв  арга  нь  AddRange методыг ашиглах явдал юм. Гэвч зарим тохиолдолд Add эсвэл Insert‐г ашиглан нэг  нэгээр  нь  нэмэх  шаардлага  байж  болно.  Энэ  үед  шаардлагагүй  илүү зуралтуудаас зайлсхийхийн тулд BeginUpdate, EndUpdate методуудыг хамтад нь хэрэглэж болно.   private void updateListBox() {     listBox.BeginUpdate();     foreach(SailboatSlip slip in Marina) {         listBox.Items.Add(slip.boat);     }     listBox.EndUpdate(); } 

Энэ жишээнд харуулснаар BeginUpdate метод нь контролын зуралтыг зогсооно. Бүх  элементүүд  шинэчлэгдэсний  дараа  EndUpdate  дуудагдаж  контролыг шинэчилж зурна. 

2.5.2 Элемент сонгох  Сонгогдсон  элементийн  индексийг  авахад  SelectedIndex  пропертиг  ашиглана. Хэрэв элемент сонгогдоогүй бол ‐1 утга буцаана. Сонгогдсон элементийг устгах жишээг дараахь кодод үзүүлэв.  if(listBox.Items.Count != 0) {     int index = listBox.SelectedIndex;     if(index != ‐1) {         listBox.Items.RemoveAt(index);     }     else {         MessageBox.Show(ʺYou must select an item to removeʺ,                         ʺCanʹt remove itemʺ,                         MessageBoxButtons.OK,                         MessageBoxIcon.Hand);     } } else {     MessageBox.Show(ʺThe list box is emptyʺ,                     ʺNothing to removeʺ,                     MessageBoxButtons.OK,                     MessageBoxIcon.Hand); } 

Хэрэв  контрол  хэд  хэдэн  элемент  сонгох  боломжтой  бол  SelectedIndex проперти  нь  тэдгээрээс  аль  нэгний  индексийг  буцаана.  Индэкс ашиглалгүйгээр  сонгогдсон  объектыг  шууд  гарган  авахад  SelectedItem пропертиг ашиглаж болно.  

Page 82: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐82‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Олон  элемент  сонгох  боломжтой  ListBox‐той  ажиллаж  байх  үед  сонгогдсон элементүүдийг авахад SelectedIndices пропертиг ашиглана: 

ListBox.SelectedIndexCollection indices = listBox.SelectedIndices; foreach(int index in indices) {     Trace.WriteLine(ʺSelected index – ʺ + index.ToString()); } 

2.6 CheckedListBox 

CheckedListBox класс нь ListBox классаас удамшсан бөгөөд жагсаалт дотор check box‐уудыг  хэрэглэх  боломж  олгодог.  CheckedListBox  класс  нь  контролын элементүүдтэй ажиллах дараахь өгөгдлийн цуглуулгуудыг агуулна. 

• CheckedListBox.CheckedItemCollection  ‐  сонгогдсон  элементүүдийн олонлог 

• CheckedListBox.CheckedIndexCollection  ‐  сонгогдсон  элементүүдийн индексүүдийн олонлог 

CheckedItemCollection  төрлийн  олонлогыг  гарган  авахад  CheckedItems пропертиг ашиглана: 

CheckedListBox.CheckedItemCollection ci = checkedListBox.CheckedItems; 

CheckedIndices  проперти  нь  CheckedIndexCollection  олонлогыг  гарган  авахад хэрэглэгдэнэ: 

CheckedListBox.CheckedIndexCollection ci = null; ci = checkedListBox.CheckedIndices; 

Тодорхой  нэг  элемент  сонгогдсон  эсэхийг  мэдэхэд  GetItemChecked  методыг ашиглана: 

bool isChecked = checkedListBox.GetItemChecked(index);  2.6 ComboBox  ComboBox  контрол  нь  TextBox  ба  ListBox  контролуудын  хослол  юм.  Тиймээс ComboBox класс нь ListBox ба TextBox классуудын шинжүүдийг удамшин авсан байдаг.   ComboBox‐н  үзэгдэх  хэлбэрийг  өөрчлөхөд DropDownStyle  пропертиг  ашиглах ба хэлбэрийг өөрчлөхөд ComboBoxStyle тоочих төрлийн утгуудыг ашигладаг.  Утга  Тайлбар Simple  Жагсаах  хэсэг  нь  үргэлж  харагдах  бөгөөд  хэрэглэгч  засах 

боломжтой DropDown  Жагсаах хэсэг нь харагдахгүй бөгөөд хэрэглэгч засах боломжтой 

Page 83: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐83‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

DropDownList  Жагсаах хэсэг нь харагдахгүй бөгөөд хэрэглэгч засах боломжгүй  

Контролын  хэлбэрийг  ажиллах  үед  өөрчлөх  боломжтой,  үүнд  дараахь пропертинуудыг ашиглаж болно: 

• DropDownWidth  ‐ жагсаах хэсгийн өргөнийг заана • DroppedDown  ‐ жагсаах хэсэг харагдах эсэхийг заана • Height  ‐ энгийн ComboBox‐н хувьд өндөрийг заана • MaxDropDownItems  ‐  жагсаах  хэсэгт  харагдах  хамгийн  их  элементийн тоо 

2.7 ScrollBar 

Өгөгдсөн мужаас их хэмжээтэй мэдээлэл харуулах  шаардлагтай үед гүйлгэгч элементийг ашигладаг.  

.NET  Framework  нь  2  төрлийн  гүйлгэгчтэй.  HScrollBar  класс  нь  хэвтээ, VScrollBar  класс  нь  босоо  гүйлгэгчийг  үүсгэхэд  хэрэглэгддэг.  Эдгээр  классууд ScrollBar классаас удамшсан. 

Ихэнхи  тохиолдолд  гүйлгэгчийг  үүсгэх  шаардлагагүй,  олонхи  цонхнууд автомат  гүйгчтэй  байдаг;  эдгээр  классууд  нь  ScrollableControl  классаас удамшсан байдаг. ScrollableControl  классаас шууд бусаар удамшсан классуудын нэг  нь  Form  класс  юм.  Үндсэн  автомат  гүйлгэгчийг  харуулахын  тулд  ердөө AutoScroll пропертиг true болгоод л болно: 

AutoScroll = true; 

AutoScroll‐с гадна дараахь пропертинууд гүйлгэгчийн шинжэд нөлөөлнө: 

• AutoScrollMargin ‐  Агуулагч  цонхны  ирмэг  ба  хүү  цүнхны  хоорондох шаардлагатай зай. Гүйлгэгч нь энэ нөөц зайг тооцоолон үүсгэгддэг. 

• AutoScrollMinSize – Энэ өгөгдсөн  хэмжээнээс цонхны хэмжээ бага болох үед гүйлгэгч автоматаар харагдана. 

AutoScrollMargin  ба AutoScrollMinSize  пропертинууд  Size  төрлийн  утгыг  авна. Size  бүтэц  нь  тэгш  өнцөгтийн  хэмжээсийг  илэрхийлэхэд  Windows  Forms классуудад өргөн ашиглагддаг. Size объектыг дараахь байдлаар байгуулж болно: 

Size minimumSize = new Size(150, 200); 

Анхны  төлвөөр, AutoScrollMargin  ба AutoScrollMinSize  пропертинууд 0  өндөр, өргөн бүхий хэмжээнүүдтэй байдаг.  Хэрэв цонхон дээрх контролыг хүрээлээд зай хэрэгтэй бол дараахь байдлаар зааж болно: 

AutoScrollMargin = new Size(50, 50); 

Page 84: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐84‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Дараахь жишээнд цонхны өндөр,  өргөн 400‐ээс  бага  болвол  гүйлгэгч  элемент автоматаар харагдана гэдгийг зааж байна. 

AutoScrollMinSize = new Size(400, 400);  2.8 Агуулагч элементүүд 

Форм нь хүү контролуудыг агуулдаг элемент юм. Хүү контролуудыг агуулагчид нэмж  болно,  энэ  үед  хүүгийн  шинжүүд  нь  агуулагчийнхаа  шинжийг дуурайдаг.  Жишээлбэл,  агуулагчын  дэвсгэр  өнгө  нь  хүү  контролын  дэвсгэр өнгөөр сонгогддог. Хэрэв агуулагч үл үзэгдэх бол хүү контролууд үл үзэгдэнэ, хэрэв агуулагч идэвхгүй бол хүү контролууд мөн идэвхгүй байна. 

Form  класс нь хамгийн энгийн агуулагч элемент юм. Түүнээс  гадна 2  агуулагч байдаг: 

• GroupBox – контролуудыг бүлэглэх боломж олгоно, гарчиг байж болно • Panel ‐   контролуудыг  бүлэглэх  боломж  олгоно,  гүйгч  элементийг дэмжинэ 

Эдгээр контролууд нь бусад контролуудыг агуулах, өөр хооронд нь тусгаарлах боломж олгодог. 

Контролуудыг  агуулах  нийдлэг  нэг  хэрэглээ  бол  radio  button‐уудыг  бүлэглэх юм. Ингэснээр нэг цонхон дээр хэд хэдэн бүлэг radio button‐ууд байх боломж бүрдэнэ. 

Агуулагч  дотор  контролыг  суулгаж  байрлуулахад  Toolbox  цонхноос  чирч агуулагч  дотор  аваачдаг.  Өмнө  байгаа  контролуудын  байрлалыг  солих  бол таслах, оруулах хослолуудыг хэрэглэж болно (Ctrl+X, Ctrl+Y). 

2.9 StatusBar 

Төлвийн  зурвас  нь  хэрэглэгчид  гэдрэг  мэдээлэл  өгөхөд  ашиглагддаг. Тухайлбал,  цэсний  элементүүдийн  тайлбар  тодорхойлолт,  програмын  тухайн үеийн төлөвийг харуулах  гэх мэт.   

Page 85: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐85‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 

Төлвийн зурвас нь StatusBar классын тусламжтай үүсдэг ба автоматаар цонхны доод хэсэгт байрлана.  

Төлвийн  зурвасыг  хэрэглэхдээ  харагдах  мужийг  хэд  хэдэн  самбаруудад хуваадаг  бөгөөд  эдгээр  самбарууд  нь  тодорхой  төрлийн  мэдээллүүдийг харуулах зорилготой байдаг. StatusBarPanel класс нь нэг самбарыг төлөөлөх ба дараахь пропертитэй. 

• Alignment – Хэвтээ чиглэлд байрлалыг заана • AutoSize – Хэмжээ нь автоматаар өөрчлөгдөх эсэхийг илэрхийлнэ • BorderStyle – Самбарын хүрээний хэлбэрийг заана • MinWidth  ‐ Самбарын хамгийн доод хэмжээ. AutoSize утга нь None  гэж заагдсан үед энэ пропертигийн утга нь Width –тэй тэнцүү байна 

• Style – Самбарын  зурагдах  хэлбэрийг  тодорхойлно,  үндсэн  утга  нь StatusBarPanelStyle.Text  байдаг.  Өөрийн  загвараар  самбарыг  зурах  үед StatusBarPanelStyle.OwnerDraw утгыг оноодог 

• Text – Самбарт дүрслэгдэх текст • Width – Самбарын өргөн 

2.10 ProgressBar 

ProgressBar контрол нь процессийн явцыг хэрэглэгчид харуулахад хэрэглэгддэг. Тухайлбал, файл хуулах зэрэгт ProgressBar контрол дээр явцыг харуулдаг. 

Дараахь  метод,  пропертинууд  нь  ProgressBar  контролд  дүрслэгдэх  утгыг өөрчлөхөд ашиглагдана: 

• PerformStep ‐ Step  пропертид  заагдсан  алхмаар  контролын  утгыг өөрчлөнө 

• Increment  ‐ Өгөгдсөн параметерээр контролын утгыг өөрчлөнө • Value  ‐ Progress bar‐н одоогийн байрлал • Step ‐ Өөрчлөгдөх алхам • Minimum – Доод утга 

Page 86: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐86‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

• Maximum – Дээд утга 

ProgressBar  контрол  нь  процессийн  хэдэн  хувьтай  явагдаж  байгааг  харуулдаг учраас доод,  дээд утгуудыг хэрэглэдэг. Анхны доод утга нь 0,  дээд утга нь 100 байдаг. 

Энэ  дээд,  доод  утгуудыг  өөрчлөх  нэг  шаардлага  нь  тодорхой  тооны элементүүдтэй  ажиллахад  хялбар  болгодог.  Тухайлбал  доод  утгыг  нь  дараахь байдлаар заана: 

progressBar.Minimum = 50; 

Дээд утгыг нь дараахь байдлаар заана: 

progressBar.Maximum = 125; 

Ерөнхийдээ заасан алхмаар утгыг ахиулахад PerformStep методыг ашигладаг: 

private void timer_Tick(object sender, System.EventArgs e) {     progressBar.PerformStep();     if(progressBar.Value == progressBar.Maximum) {         // Timer period elapsed.          

           } } 

Дарахь жишээнд  ажилбарын явцыг  харуулахад Value  пропеортиг  ашилагасан байна: 

progressBar.PerformStep(); progressLabel.Text = string.Format(ʺ{0}% completeʺ, progressBar.Value); 

2.11 PictureBox 

PictureBox  контрол  нь  зурган  мэдээллийг  харуулахад  хэрэглэгдэнэ.  Зургийг харуулахад  шаардлагатай  үйлдүүдийг  PictureBox  классаар  зохион  байгуулсан байдаг. 

PictureBox классын хамгийн чухал проперти нь Image юм, энэ нь контрол дээр зурагдах зургийг заахад ашиглагдана: 

pictureBox.Image = Image.FromFile(@ʺC:\Windows\winnt256.bmpʺ); 

Ихэнхи тохиолдолд зургийн хэмжээ ба PictureBox контролын хэмжээ ялгаатай болдог.  SizeMode  проперти  нь  зураг  болоод  PictureBox  контролууд  бие 

Page 87: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐87‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

биенээсээ  хамааран  яаж  хэмжээгээ  өөрчлөхийг  заадаг.  Энэ  проперти  нь PictureBoxSizeMode тоочих төрлийн утгууд авах ба дараахь хүснэгтэд харуулав. 

Утга  Тайлбар AutoSize  Зургийн хэмжээгээр контролын хэмжээ өөрчлөгдөнө CenterImage  Зураг  контролын  төвд  голлоно,  хэрэв  зургийн  хэмжээ 

контролын  хэмжээнээс  том  бол  зургийн  ирмэгүүд таслагдана 

Normal  Зураг  контролын  зүүн,  дээд  өнцөгт  дүрслэгдэнэ.  Хэрэв зургийн хэмжээ контролоос том бол ирмэгүүд нь таслагдана 

ScretchImage  Контролын хэмжээнд тохируулж зургийн хэмжээг өөрчлөнө 

2.12 TabControl 

Цонх  эсвэл  диалог  цонхон  дээрх  зайг  зөв  ашиглахад TabControl‐г  ашиглах  нь тохиромжтой  байдаг. TabControl  нь  нэг  талбай  дээр  олон  хуудсуудыг  агуулах боломжтой  бөгөөд  контролын  толгой  дахь  шошгууд  дээр  дарж  хуудсуудыг сонгож болно.  

 

 

Page 88: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐88‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

TabPage  класс  нь  нэг  хуудсыг  дүрслэнэ.  TabControl  дээр  хуудсуудыг  нэмэх замаар  олон  хуудастай  болж  болно.  TabControl  нь  дараахь  метод,  пропертиг агуулна. 

• Alignment – Хуудсуудыг яаж цэгцлэхийг заана • Appearance – Контролын зурагдах хэлбэрийг заана • Multiline – Олон мөр хуудасууд дүрслэх эсэхийг заана • SelectedIndex – Сонгогдсон хуудсын индекс • SelectedTab – Сонгогдсон хуудас • SizeMode – Хуудсуудын хэмжээ яаж өөрчлөгдөхийг заана • TabCount  ‐ Хуудсын тоо • TabPages – Хуудаснуудын олонлог 

2.13 Toolbar 

Хэрэгслийн  мөр  нь  хүссэн  командаа  цэснээс  сонголгүйгээр  хулганы  нэг даралтаар хялбархан хийх боломж олгодог. Програмд олон дахин хэрэглэгддэг командуудыг хэрэгслийн мөр дээр байрлуулах нь оновчтой. 

 

2.14 TreeView 

TreeView контрол нь мод хэлбэрээр өгөгдлийг харуулахад хэрэглэгдэнэ. Мод нь зангилаануудтай  байх  бөгөөд  хамгийн  оройн  зангилааг  үндэс,  салаалсан зангилааг  хүү  гэж  хэлдэг.  Модтой  ажиллахад  зарим  чухал  класс,  проперти, методуудыг дараахь хүснэгтэд харуулав. 

Класс  Метод/проперти Тайлбар TreeNode  TreeNode  Нэг зангилаа байгуулах TreeView  Nodes  Хүү зангилаануудын олонлог TreeView  SelectedNode  Сонгогдсон зангилаа TreeView  ExpandAll  Бүх зангилааг задлах TreeView  CollapseAll  Бүх зангилаа хумих TreeView  Nodes.Add  Зангилаа нэмэх TreeView  Nodes.Remove  Зангилаа хасах TreeView  ShowLines  Зангилаануудын  хооронд  шулуун 

харагдах эсэх 

Page 89: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐89‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

TreeView  ShowPlusMinus  Зангилааг  задлах,  хураах  товч  харагдах эсэх 

TreeView  BeginUpdate  Контрол  дээр  өөрчлөлт  хийхийг хориглоно 

TreeView  EndUpdate  Контрол  дээр  өөрчлөлт  хийхийг зөвшөөрнө 

Модыг програм ажиллаж байх үед байгуулах тохиолдолд модны үзэгдэлүүдтэй ажиллах  шаардлага  гарна.  Тухайлбал,  хэрэглэгч  тухайн  нэг  зангилааг  задлах үед  түүний  хүү  зангилаануудыг  байгуулж  дүүргэж  болно.  Энэ  зорилгод хүрэхийн тулд BeforeExpand үзэгдэл дээр боловсруулалт хийх хэрэгтэй болно: 

private void tvRegistry_BeforeExpand(object sender,                                       TreeViewCancelEventArgs e) {     tvRegistry.BeginUpdate();     foreach (TreeNode tn in e.Node.Nodes) {         AddBranch(tn);     }     tvRegistry.EndUpdate(); } 

Дараахь хүснэгтэд модны үзэгдлүүдийг харуулав. 

Үзэгдэл  Тайлбар AfterCheck  Зангилаан  дээр  check  box  сонгосны 

дараа үүснэ AfterCollapse  Зангилаа хураагдсаны дараа үүснэ AfterExpand  Зангилаа задарсны дараа үүснэ AfterLabelEdit  Зангилааны  текст  засагдсаны  дараа 

үүснэ AfterSelect  Зангилааг сонгосны дараа үүснэ BeforeCheck  Зангилаан  дээр  check  box  сонгохын 

өмнө үүснэ BeforeCollapse  Зангилааг хураахын өмнө үүснэ BeforeExpand  Зангилааг задлахын өмнө үүснэ BeforeLabelEdit  Зангилааны  текстийг  засахын  өмнө 

үүснэ BeforeSelect  Зангилааг сонгохын өмнө үүснэ ItemDrag  Мод руу элемент чирэх үед үүснэ 

 

    

Page 90: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐90‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

 

Лекц№14,15 

Үзэгдэл боловсруулалт 

Дэд сэдвүүд: 

• Үзэгдэл барих • Хулганы үзэгдэлүүд • Хулганы заагч • Цэсний үзэгдэлүүд 

Бүх  контролууд  үзэгдэл  үүсгэдэг.  Үзэгдэл  нь  бидний  сонирхож  буй  ямар  нэг зүйл  контрол  дээр  болжээ  гэдгийг  мэдээлдэг.  Олонхи  үзэгдэлүүд  хэрэглэгч контролтой харьцах үед үүсдэг. Жишээлбэл, хэрэглэгч товч дарах, текст бичих гэх  зэрэгт  үзэгдэл  үүснэ.  Эдгээр  үзэгдлийг  боловсруулснаар  цонхтой програмууд нь хэрэглэгчтэй ойлголцож, хариу үйлдэл хийж байдаг. 

Програм  нь  тухайн  үзэгдэлийг  барих  сонирхлоо  үзэгдэл  төлөөлөгчөөр дамжуулан бүртгүүлдэг. Програмаар баригдахгүй бусад үзэгдэлүүд нь тухайн контролтой  уягдсан  классаар  боловсруулагддаг.  Контролуудын  нийтлэг шинжүүд  нь  суурь  классаараа  тодорхойлогддог.  Жишээлбэл,  Control  суурь класс нь контролуудад шаардлагатай бүх зүйлсийг агуулсан байна. 

Контрол бүр маш олон тооны үзэгдэлүүдийг үүсгэж байдаг. Эдгээрийн олонх нь Control суурь классаар тодорхойлогддог. 

Зарим  үзэгдлүүд,  тухайлбал  товч  дарахад  үүсэх  Click  үзэгдэл,  бараг  байнга боловсруулагдаж байдаг. Зарим үзэгдэлүүд дэд контролуудын үзэгдэх байдал, шинжийг  өөрчлөх  боломж  олгодог.  Жишээлбэл,  цонхны  дэвсгэр  өнгө, байрлал, хэмжээ зэргийг өөрчлөхөд үзэгдэл үүсэх ба түүнд агуулагдаж байгаа хүү  контролууд  өөрийнхөө  үзэгдэх  хэлбэрийг  өөрчлөхөд  эдгээр  үзэгдэлийг ашиглана. 

Button  контрол  нь  цонхтой  програмуудад  хамгийн  өргөн  ашиглагддаг. Button классаар үүсдэг хамгийн нийтлэг үзэгдэлүүд нь: 

• Click  ‐ хэрэглэгч контролыг дарах, сонгох зэрэгт үүснэ • Disposed – контролын Dispose метод дуудагдсан үед үүснэ • DoubleClick – хэрэглэгч контрол дээр давхар‐даралт хийсэн үед үүснэ • GotFocus – контрол дээр удирдлага очсон үед үүснэ • LostFocus – контролоос удирдлага шилжсэн үед үүснэ • TextChanged  ‐   Text проперти өөрчлөгдсөн үед үүснэ • Validated – контролын агуулга шалгагдсан үед үүснэ • Validating – контролын агуулга шалгагдаж байх үед үүснэ 

Page 91: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐91‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

3.1 Үзэгдэл барих 

Үзэгдэлийг  барих  захиалга  хийхийн  тулд  үзэгдэл  баригч  бичих  ба  үүнийгээ тусгай  нэг  үзэгдэлтэй  холбож  өгдөг.  Үзэгдэл  барихын  тулд  хэд  хэдэн  арга ашиглаж болно. Хамгийн энгийн нэг арга бол үзэгдэлийн төрөлтэй тохирох нэг методыг тодорхойлох, дараа нь түүнийгээ дараахь байдлаар бүртгэх: 

public ButtonForm() {      

           closeButton.Click += new EventHandler(OnButtonClicked); }  private void OnButtonClicked(object sender, EventArgs e) {     MessageBox.Show(ʺIʹve been clickedʺ); } 

Контрол  дээр  давхар‐даралт  хийх  үед  Windows  Forms  Designer  нь  тохирох үзэгдэл боловсруулагчийг автоматаар үүсгэж бүртгэдэг. Энэ үед програмын эх кодын цонх автоматаар нээгдэж шинээр үүссэн метод дээр байрладаг. 

Контрол  нь  олон  тооны  үзэгдэл  боловсруулдаг  болохоор  энэ  тохиолдолд хамгийн  их    хэрэглэгддэг  үзэгдэлийг  барих  үзэгдэл  боловсруулагч  үүсдэг. Жишээ  нь,  if  you  button  контрол  дээр  давхар‐даралт  хийхэд  Click  үзэгдэл боловсруулагч  үүснэ.  Хэрэв  text box  контрол  дээр  давхар‐даралт  хийвэл Text‐Changed үзэгдэлд зориулсан үзэгдэл баригч үүснэ. 

Forms Designer  үзэгдэл  баригчийг  үүсгэхдээ objectname_eventname  хэлбэрийн нэршилийг  ашигладаг.  Тухайлбал,  closeButton  нэртэй  товчны  хувьд  Click үзэгдэл баригч нь closeButton_Click гэж нэрлэгдэх болно: 

private void closeBtn_Click(object sender, System.EventArgs e) {      } 

Дараа нь энэ методыг бүртгэнэ: 

this.closeBtn.Click += new System.EventHandler(this.closeBtn_Click); 

Цонх  нь  ижил  төрлийн  олон  контролуудыг  агуулах  тохиолдолд  бүгдэд  нь зориулсан  нэг  л  үзэгдэл  баригч  байж  болно.  Үзэгдэл  баригчид  дамжуулсан sender параметер нь ямар контролоос үзэгдэл үүссэнийг мэдэхэд хэрэглэгддэг: 

private void OnClick(object sender, System.EventArgs e) {     Button clickedButton = (Button)sender;     switch(clickedButton.Name) {         case ʺstandardButtonʺ:             MessageBox.Show(ʺStandard button clickedʺ); 

Page 92: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐92‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

            break;          case ʺpopupButtonʺ:             MessageBox.Show(ʺPopup button clickedʺ);             break;          case ʺflatButtonʺ:             MessageBox.Show(ʺFlat button clickedʺ);             break;          default:             MessageBox.Show(ʺUnknown button clickedʺ);             break;     } } 

Энэ  жишээнд  standardButton,  popupButton,  flatButton  товчнууд  дээрх  Click үзэгдэлийг барихад OnClick метод ашиглагдаж байна. OnClick метод нь sender параметерийг  Button  төрөл  рүү  хувиргаад,  нэрнээс  нь  хамааруулж  ялгаатай мэдэгдэлүүдийг харуулаж байна. 

Үзэгдэл боловсруулагчийг бүртгэхийн тулд дараахь байдлаар хийж болно: 

EventHandler clickHandler = new EventHandler(OnClick); standardButton.Click += clickHandler; popupButton.Click += clickHandler; flatButton.Click += clickHandler; 

Програм  ажиллах  үед  үзэгдэл  баригчийг  хасахын  тулд  дараахь  байдлаар хэрэглэж болно: 

flatButton.Click ‐= new EventHandler(OnClick);  3.2 Хулганы үзэгдэлүүд  Цонхтой  програмууд  нь  ихэнхдээ  хулганатай  ажилладаг.  Хулгана  зөөх,  дарах зэрэгт  үзэгдэл  үүсэж  програм  руу  илгээгдэж  байдаг.  Хулганаар  дараахь үзэгдлүүд үүсдэг.  Үзэгдэл  Тайлбар MouseEnter  Хулганы заагч цонх эсвэл контролын мужид орсон MouseHover  Хулганы  заагч  цонхон  дээр  хөдлөхөө  зогссон.  Энэ  үзэгдэл  нь 

MouseEnter үзэгдлийн дараа хулганы заагч хөдлөхөө зогсоход үүсдэг MouseLeave  Хулганы заагч цонхны мужаас гарсан MouseMove  Хулганы заагч шинэ байрлалд шилжсэн MouseWheel  Хулганы өнхрүүл хөдөлсөн  Дээрх  хүснэгт  дэх  үзэгдлүүдийн  олонхи  нь  EventHandler  төрлийнх  ба MouseMove, MouseWheel үзэгдэлүүд нь MouseEventHandler төрлийнх юм.  

Page 93: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐93‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

MouseMove += new MouseEventHandler(form_MouseMove); private void form_MouseMove(object sender, MouseEventArgs e) {      } 

Жишээнд харуулснаар MouseEventHandler төрлийн үзэгдэл нь MouseEventArgs параметерийг  хүлээж  авч  байна.  MouseEventArgs  класс  нь  дараахь  хулганы төлөв болон байрлалын талаар нэмэлт мэдээллээр хангадаг. 

• Button ‐  хулганы аль товч дарагдсаныг заана • Clicks – хулганы даралтын тоо • Delta  ‐ хулганы өнхрүүлийн эргэлтийн байрлал • X ‐ хулганы заагчын x координат • Y – хулганы заагчын y координат 

Ердийн  EventArgs  параметер  дамжуулдаг  үзэгдэл  боловсруулж  байгаа тохиолдолд  хулганы  координатыг  яаж мэдэх  вэ? Form  класс  нь MousePosition пропертитэй бөгөөд энэ нь хулганы байрлаж байгаа координатыг буцаадаг: 

private void main_Click(object sender, System.EventArgs e) {     Point mousePoint = PointToClient(MousePosition);     string msg = string.Format(ʺMouse click at X:{0}, Y:{1}ʺ,                                 mousePoint.X,                                 mousePoint.Y);     MessageBox.Show(msg); } 

MousePosition‐н  буцаах  утга  нь  xy  байрлалыг  агуулах  Point  бүтэц  юм.  Энэ буцаасан  Point  бүтэц  нь  тухайн  цонх  буюу  контролоос  хамааралгүй  бүтэн дэлгэцийн  хувьд  хамаатай  координат  юм.  Тиймээс  энэ  жишээнд  байрлалыг цонхны координат руу хувиргахад PointToClient методыг ашиглаж байна. 

Дараахь  хүснэгт  дэх  MouseButtons  тоочих  төрөл  нь  хулганы  товчнуудыг илэрхийлнэ. 

Утга  Тайлбар None  Хулганы товч дарагдаагүй Left  Үндсэн  (ихэнхдээ  зүүн)  товч 

дарагдсан Middle  Дунд товч дарагдсан Right  Туслах  (ихэнхдээ  баруун)  товч 

дарагдсан XButton1  Эхний XButton дарагдсан XButton2  Хоёр дахь XButton дарагдсан 

Сүүлийн 2 мөр нь Microsoft IntelliMouse хулганы товчнууд юм, энэ хулгана нь 5 товчтой байдаг ба хуудас хооронд шилжилт хийхэд ашиглагддаг.   

Page 94: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐94‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Жишээ нь MouseWheel үзэгдлийг барихад дараахь кодыг ашиглаж болно.  nameListBox.MouseWheel += new MouseEventHandler(list_MouseWheel); private void list_MouseWheel(object sender, MouseEventArgs e) {      } 

Хулганы  хамгийн  өргөн  хэрэглээний  нэг  нь  элементийг  сонгох  юм.  Элемент сонгоход оролцох үзэгдлүүд нь MouseDown, MouseUp, Click, DoubleClick юм. 

3.3 Хулганы заагч  Хэрэглэгчид  гэдрэг  хариу  өгөх  аргуудын  нэг  нь  хулганы  заагчыг  ашиглах юм. Тухайлбал, хулганы заагчын хэлбэрийг өөрчилж хэрэглэгчид түр хүлээх, эсвэл ажилбар дууслаа зэргийг ойлгуулж болно.  Хулганы заагчыг өөрчлөхөд  цонхны Cursor пропертиг ашигладаг.   Cursor = Cursors.WaitCursor; 

Cursor пропертиг мөн одоогийн хулганы заагчын хэлбэрийг мэдэхэд хэрэглэж болно. 

Cursor oldCursor = Cursor; . . . 

Cursor = oldCursor; 

Cursors класс нь сдандарт курсорын хэлбэрүүдийг агуулсан байдаг. 

Утга  Тайлбар AppStarting   Програм эхлэж байгааг илэрхийлсэн хэлбэр Arrow   Сум хэлбэрийн заагч Cross   Ихэвчлэн зургын хэсгийг сонгох зэрэгт гардаг. Default   Үндсэн хэлбэр Hand   Ихэвчлэн вэб дээр гипер холбоосыг илэрхийлдэг Help   Тусламж HSplit   Хэвтээ тусгаарлагчыг илэрхийлнэ IBeam  Текст өгөгдөл засварлах үед хэрэглэгдэнэ No  Хориглосон  заагч.  Ихэвчлэн  чирэх‐тавих  үед  буруу 

байрлалд тавих тохиолдолд хэрэглэгддэг UpArrow   Дээшээ сум VSplit   Босоо тусгаарлагчыг илэрхийлнэ 

Page 95: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐95‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

WaitCursor   Хүлээх, систем завгүй байна SizeAll   Дөрвөн чиглэлд хэмжээг өөрчлөх SizeNESW   Зүүн доош, баруун дээш чиглэлд хэмжээг өөрчлөх SizeNS   Дээш, доош чиглэлд хэмжээг өөрчлөх SizeNWSE   Зүүн дээш, баруун доош чиглэлд хэмжээг өөрчлөх SizeWE   Баруун, зүүн чиглэлд хэмжээг өөрчлөх NoMove2D   Хулганы заагчыг хөдөлгөх боломжгүй, харин хэвтээ, босоо 

чиглэлд гүйлгэж болно NoMoveHoriz    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ  цонхыг  хэвтээ 

чиглэлд гүйлгэж болно NoMoveVert   Заагчыг хөдөлгөх боломжгүй, гэхдээ цонхыг босоо чиглэлд 

гүйлгэж болно PanEast    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ  цонхыг  зүүн  тийш 

гүйлгэж болно PanNE    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ  цонхыг  зүүн  дээш 

гүйлгэж болно PanNorth   Заагчыг хөдөлгөх боломжгүй, гэхдээ цонхыг дээш гүйлгэж 

болно PanNW    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ  цонхыг  баруун  дээш 

гүйлгэж болно PanSE    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ  цонхыг  зүүн  доош 

гүйлгэж болно PanSouth  Заагчыг хөдөлгөх боломжгүй, гэхдээ цонхыг доош гүйлгэж 

болно PanSW    Заагчыг  хөдөлгөх  боломжгүй,  гэхдээ цонхыг  баруун  доош 

гүйлгэж болно PanWest    Заагчыг  хөдөлгөх боломжгүй,  гэхдээ цонхыг баруун тийш 

гүйлгэж болно 

Дээрх стандарт заагчын хэлбэрүүдээс  гадна өөрийн заагчыг дараахь байдлаар ашиглаж болно. 

private void SetSmileyCursor(){     Cursor _smileyCursor = new Cursor(ʺ..\\..\\smiley.curʺ);     Cursor = _smileyCursor; } 

Энд “smiley.cur” файл нь хулганы заагчын дүрсийг агуулсан файл бөгөөд файл систем дээр байрлах ёстой. 

3.3 Гарны үзэгдэлүүд 

Гарны товчлуур дээр дарахад 3 төрлийн үзэгдэл үүсдэг.   

Page 96: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐96‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

• KeyDown –  Товч дарагдсан,  товчны төлөв, мэдээллүүд агуулагдана  (Ctrl, Shift, and Alt keys). 

• KeyPressed –  Тэмдэгт  товч  дарагдсан.  Энэ  үзэгдэл  нь  бүх  товчны  хувьд үүсэхгүй. 

• KeyUp – Товч салгагдсан. 

KeyUp  ба  KeyDown  үзэгдэлүүд  нь  KeyEventArgs  төрлийн  параметерүүдтэй байдаг,  энэ  нь  EventArgs  классын  дэд  класс  юм.  KeyEventArgs  нь  гарнаас оруулсан өгөгдлийг боловсруулахад хялбар болгосон пропертинуудыг агуулна: 

• Alt ‐ Alt товч дарагдсан бол true; эсрэг тохиолдолд false утга буцаана. • Control ‐ Ctrl товч дарагдсан бол true; эсрэг тохиолдолд false утга буцаана. • Handled – Мэдэгдэл боловсруулагдсан эсэх талаар Boolean утга буцаана. • KeyCode –  Дарагдсан  товчны  код, Keys  тоочих  төрлийн  байна. KeyCode нь Shift, Ctrl, Alt зэрэг товчны хослолуудыг агуулахгүй. 

• KeyData – Дарагдсан  товчны  код,  Alt,  Shift,  Ctrl  зэрэг  хослол  товчнууд дарагдсан бол цуг агуулна. 

• KeyValue ‐ KeyData –ийн бүхэл тоон хувилбар. • Modifiers ‐ Alt, Shift, Ctrl товчнууд дарагдсан үед кодыг нь агуулна. • Shift ‐ Shift товч дарагдсан бол true; эсрэг тохиолдолд false утга буцаана. 

Alt, Control, Shift  зэрэг  товчнууд нь бусад  товчнуудын утгыг өөрчлөх үүрэгтэй байдаг. Ийм хувиргагч товч дарагдсан эсэхийг таних нэг арга нь дараахь кодод харуулсан байна: 

if(e.KeyCode == Keys.Q) {     if(e.Shift == true) {               }     if(e.Control == true){               } }  

Өөр  нэг  арга  нь  Modifiers  пропертиг  ашиглах,  энэ  проперти  нь  хэд  хэдэн хувиргагч  товчлуур  дарагдсан  үед  хэд  хэдэн  утга  агуулна.  Яг  ямар  товчнууд дарагдсан эсэхийг мэдэхийн тулд дараахь кодыг ашиглаж болно: 

if(e.KeyCode == Keys.B) {     if(e.Modifiers == (Keys.Control │ Keys.Shift) {               } }  

Page 97: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐97‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Хэрэв  олон  хувиргагч  товчны  хослол  шалгах  гэж  байгаа  бол  Modifiers пропертиг  ашиглана,  хэрэв  нэг  хувиргагч  товчны  төлөв  шалгах  бол KeyEventArgs классаас тохирох нэг пропертиг ашиглах хэрэгтэй. 

KeyPress үзэгдэл нь KeyDown ба KeyUp үзэгдэлүүдийн хооронд үүсдэг үзэгдэл юм.  KeyDown  ба  KeyUp  үзэгдэлүүдтэй  адилгүй  нь  KeyPress  үзэгдэл KeyPressEventArgs  төрлийн  параметертэй  байдаг. KeyPressEventArgs  класс  нь товчны  код,  хувиргагч  товчнуудын  тухай  мэдээлэл  өгөхгүй  бөгөөд  дараахь пропертитэй: 

• Handled ‐  Үзэгдэл боловсруулагдсан эсэх мэдээлэл • KeyChar – Дарагдсан товчны тэмдэгт утга 

KeyPress  үзэгдэл  нь  энгийн  текст  оруулах  үед  тохиромжтой юм. KeyDown  ба KeyUp үзэгдэлүүд нь функциональ болон удирдах товчнуудыг боловсруулахад тохиромжтой. 

Keys  тоочих  төрөл  нь  гарнаас  үүсэх  бүх  товчлуурын  кодуудыг  агуулдаг. Нийтдээ 183 утгыг агуулах бөгөөд энд бүгдийг тоочих боломжгүй учраас зарим жишээг харуулав. 

Утга  Тайлбар A  A тэмдэгт F5  F5 удирдах товч D9  9 цифр LShiftKey  Зүүн Shift товч 

3.3.1 Фокус 

Хугацааны нэг эгшинд бүх програм, бүх контролд гарнаас өгөгдөл оруулах нь боломжгүй  юм.  Гарнаас  өгөгдөл  оруулахын  тулд  тухайн  цонх  эсвэл  контрол дээр удирдлага  (focus) шилжсэн байх ёстой. Жишээ нь,  text box  контрол дээр фокус  шилжсэн  үед  босоо  зураас  (|)  харагдаж  тэмдэгт  оруулах  боломжтой болдог. 

Фокусыг өгөгдсөн контрол руу шилжүүлэхийн тулд Focus методыг ашигладаг. Мөн  Focus  метод  нь  тухайн  контрол  дээр  фокус  байрласан  бол  true,  эсрэг тохиолдолд false утга буцаадаг. 

if(nameTextBox.Focus() == false) {     Trace.WriteLine(ʺCouldnʹt set focus to text boxʺ); }  

Control класс нь фокусыг удирдах дараахт пропертиг агуулдаг: 

• CanFocus –  Контрол  дээр  фокус  шилжих  боломжтой  бол  true,  эсрэг тохиолдолд false утга буцаана 

Page 98: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐98‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

• ContainsFocus – Тухайн  контрол  эсвэл  түүний  хүү  контрол  дээр  фокус байрласан бол true, эсрэг тохиолдолд  false утга буцаана 

• Focused – Контрол дээр фокус байрласан бол true, эсрэг тохиолдолд false утга буцаана 

Контрол  нь  идэвхтэй  бөгөөд  хамийн  дээд  түвшинд  байрлах  үед  фокус  авах боломжтой  байдаг.  Фокус  авах  боломжтой  эсэхийг  CanFocus  проперти ашиглан дараахь байдлаар шалгаж болно: 

if(nameTextBox.CanFocus) {  }  

ContainsFocus  проперти  нь  тухайн  контрол  эсвэл  түүний  хүү  контролуудаас фокус авсан эсэхийг мэдэхэд чухал байдаг: 

if(this.ContainsFocus) {      } 

Фокусыг шалгахын оронд дараахь үзэгдэлүүдийг ашиглаж болно: 

• Enter – Контрол эсвэл түүний хүү контролуудаас аль нэг нь фокус авсан үед үүснэ 

• Leave ‐ Контрол эсвэл түүний хүү контролуудын аль нэгээс фокус гарсан үед үүснэ 

Enter  ба  Leave  үзэгдэлүүдийг  хэрэглэгчийн  интерфэйсийг  сайжруулахад ашиглаж  болно,  жишээлбэл,  контрол  фокус  авсан  үед  түүнтэй  холбоотой тусламж мэдээллийг харуулж болно: 

private void nameTextBox_Enter(object sender, System.EventArgs e) {     helpLabel.Text = ʺEnter the userʹs first and last nameʺ; }  private void nameTextBox_Leave(object sender, System.EventArgs e) {     helpLabel.Text = ʺʺ; } 

3.4 Цэсний үзэгдэлүүд 

Цэс  нь  цонхтой  програмуудад  нийтлэг  хэрэглэгддэг  хэрэглэгчийн  интерфэйс юм. Цэс нь мод хэлбэрийн шаталсан холбоо хамааралтай ба ихэвчлэн тодорхой тооны оройн элементүүдийг агуулсан байдаг. Оройн элементүүд нь задрах дэд цэсүүдийг  агуулсан  байдаг,  дэд  цэсүүд  нь мөн  өөртөө  дэд  цэсүүдийг  агуулж болно.  

Page 99: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐99‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Цэс бүхий хэрэглэгчийн интерфэйс үүсгэхдээ дараахь дүрмүүдийг баримтлах хэрэгтэй. 

• Цэсний  элемент  нь  туслах  тэмдэгттэй  байх  хэрэгтэй  –  энэ  тэмдэгт  нь цэсний  элементийн  нэг  хэсэг  бөгөөд  Alt  товчтой  хамтран  тухайн элементийг  сонгоход  хэрэглэгдэнэ. Жишээлбэл, Ихэвчлэн File  цэс  нь F тэмдэгттэй  холбогдсон  байдаг  ба  Alt+F  товчны  хослолоор  File  цэсийг дуудаж болдог.  

• Дэд цэс агуулдаггүй шууд команд дууддаг цэсний элемент нь нэрнийхээ ард  анхааруулсан  тэмдэгттэй  байх  хэрэгтэй.  Энэ  нь  тухайн  цэсийг сонгосон  үед  шууд  команд  дуудагдах  болно  гэдгийг  хэрэглэгчид анхааруулна. 

• Диалог цонх зэрэг хэрэглэгчээс нэмэлт мэдээлэл шаардах цонх харуулах цэс нь нэрнийхээ ард (...) –тэй байх нь зүйтэй. 

Хэрэглэгч цэснээс сонголт хийх үед дараахь үзэгдлүүд үүснэ. 

• Popup – Дэд  цэс  задрах  үед  үүснэ.  Энэ  үзэгдэл  нь  дэд  цэсний элементүүдийг динамикаар өөрчлөх боломж олгоно. 

• Select – Цэсний  элемент  сонгогдсон,  гэхдээ  дарагдаагүй.  Энэ  үзэгдэл  нь сонгох  гэж  буй  цэсний  талаар  status  bar  зэрэг  контролууд  дээр  туслах мэдээлэл харуулахад чухал байдаг. 

• Click – Хэрэглэгч цэсний элементийг сонгосон. Энэ нь цэстэй холбоотой үзэгдэлүүдээс  хамгийн  их  хэрэглэгддэг  бөгөөд  энэ  үзэгдэлийн  цаана тодорхой үйлдлүүдийг хийж байдаг. 

Эдгээр  цэсний  үзэгдэлүүд  нь  тодорхой  нэг  цэс  сонгогдсон  эсэх  талаар мэдээлнэ,  харин  сонголтыг  цуцалсан  талаар  талаар  ямар  нэг  зүйл  хэлэхгүй. Form  класс  нь  цэс  задраад  цуцлагдсан  тухай  мэдээлэл  өгөх  дараахь үзэгдэлүүдийг агуулна: 

• MenuStart – Цэс дээр фокус очих үед үүснэ • MenuComplete – Цэснээс фокус гарах үед үүснэ 

MenuStart  үзэгдэл  нь  ерөнхийдөө  хэрэглэгчийн  интерфэйс  элементүүдийг өөрчлөхөд хэрэглэгддэг. Тухайлбал, цэс сонгогдсон үед тодорхой контролуудыг идэвхгүй болгох гэх мэт. 

MenuComplete  үзэгдэл  нь  MenuStart  үзэгдэлээр  хийгдсэн  үйлдлүүдийг буцаахад хэрэглэгддэг. Энэ үзэгдэл нь хэрэглэгч цэсийг сонгож дууссаны дараа эсвэл сонголтыг цуцлаад өөр объект сонгосон үед үүснэ. 

    

Page 100: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐100‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Лекц№16 

Цонхны график 

Дэд сэдвүүд: 

• Цонхны геометр • Зуралт хийх 

4.1 Цонхны геометр 

GDI+  нь  цонхтой  програмуудад  зориулсан  график  дүрсүүдийг  зурах  шинэ хэрэгсэл юм. GDI+ нь Windows‐н хуучны хувилбаруудад хэрэглэгддэг Graphical Device Interface (GDI)‐г өргөтгөсөн шинэ хувилбар юм.  

Цонхон дээр шууд зуралт хийхэд Graphics классын методуудыг ашигладаг. Мөн энэ  классыг  ашиглан  цонхны  горим,  дэлгэцийн  боломжуудын  тухай мэдээллүүдийг авах боломжтой. 

Дүрсүүд  болон  тэдгээрийн  байрлал,  хэмжээг  тодорхойлоход  Point,  Size, Rectangle зэрэг бүтцүүдийг өргөн ашигладаг. 

4.1.1 Цэгийн Байрлал 

Point бүтэц нь 2 хэмжээст цонхны гадаргуу дээр байрлал тодорхойлох, шулуун, тэгш өнцөгт болон бусад дүрсүүдийг тодорхойлоход өргөн ашиглагддаг. Point нь дараахь 2 проперти агуулна. 

• X – хэвтээ чиглэлт x координат • Y – босоо чиглэлд y координат 

Point бүтцийн үндсэн байгуулагч нь (0,0) утгатай хоосон цэгийг үүсгэдэг. Цэг нь хоосон эсэхийг IsEmpty пропертигээр шалгаж болно.  if(pt.IsEmpty) {     // pt is an empty Point structure. } 

Pointбүтэц үүсгэх хамгийн энгийн арга нь xy координатаар нь үүсгэх юм: 

int x = 10; int y = 20; Point pt = new Point(x, y);  

PointF  бүтэц  нь  Point  бүтэцтэй  төстэй  бөгөөд  ялгаа  нь  кооринатууд  нь  илүү сайн нарийвчлалтай бодит тоон утгуудаар илэрхийлэгддэг. 

Page 101: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐101‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

float x = 22.4f; float y = 17.8f; PointF pt = new PointF(x, y);  

PointF  төрлөөс  Point  төрөл  рүү  хөрвүүлэхэд  Point  бүтцийн  дараахь  статик методуудыг ашигладаг: 

• Ceiling  ‐  координатыг  дараагийн  их  утгатай  бүхэл  тоо  руу  тоймлож хөрвүүлнэ 

• Round – координатыг ойролцоо бүхэл тоо руу тоймлож хөрвүүлнэ • Truncate –  координатыг  ойрын  бага  утгатай  бүхэл  тоо  руу  тоймлож хөрвүүлнэ 

Point  төрлөөс  PointF  төрөл  рүү  хөрвүүлэхэд  далд  хөрвүүлэлт  автоматаар хийгдэнэ. 

4.1.2 Дүрсийн хэмжээ 

Size бүтэц нь цонх, контрол болон бусад тэгш өнцөгт мужуудын хэмжээг заахад ашиглагддаг. Size бүтэц нь 2 байгуулагчтай: эхнийх нь Point утгыг хүлээн авна: 

Point pt; Size mySize = new Size(pt); 

Энэ  байгуулагч  нь  Point  бүтцийн  x  координатыг  урт,  y  координатыг  өндөр болгон авдаг. 

Дараагийн байгуулагч нь урт, өндөрийг бүхэл тоон утгаар хүлээн авна: 

int width = 20; int height = 10; Point pt = new Point(width, height);  

Size бүтэц нь урт, өндөрийг илэрхийлэх Width ба Height пропертитэй. 

SizeF  бүтэц  нь  Size  бүтэцтэй  төстэй  боловч  бодит  тоон  утгуудаар  хэмжээг илэрхийлдэг. 

4.1.3 Тэгш өнцөгт 

Rectangle бүтэц нь тэгш өнцөгтийн хэмжээ, байрлалыг заахад хэрэглэгдэнэ, энэ нь цонх, контрол зэргийг зурахад ашиглагддаг уламжлалт бүтэц юм. Rectangle бүтэц нь зүүн дээд өнцгийн байрлалыг заах Point бүтэц,  тэгш өнцөгтийн урт, өндөрийг илэрхийлэх Size бүтэцийн хослол юм. 

Rectangle бүтэц үүсгэхэд 2 байгуулагч байна. Эхний байгуулагч нь Point ба Size бүтцийг параметр болгон авдаг: 

Page 102: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐102‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Size  mySize = new Size(200, 300); Point startPoint = new Point(10, 10); Rectangle myRect = new Rectangle(startPoint, mySize);  

Хоёрдахь хувилбар нь тэгш өнцөгтийн хүрээг тодорхойлох 4 бүхэл тоон утгыг авдаг: 

int left = 10; int top = 10; int width = 200; int height = 300; Rectangle myRect = new Rectangle(left, top, width, height);  

Rectangle бүтэц нь дараахь пропертитэй: 

• Left • Right • Top • Bottom • Width • Height 

RectangleF нь Rectangle бүтэцтэй төстэй бөгөөд бодит тоон утгуудаар хэмжээс нь илэрхийлэгддэг. 

4.2 Зуралт хийх 

Цонхтой  програмуудын  хувьд Paint  үзэгдэлийн  цаана  зуралт  явагддаг.  Өмнөх жишээнүүдэд  үзэж  байсан  бүх  контролууд  нь  Paint  үзэгдэлийг  боловсруулж өөр өөрсдийн зуралтийг далд хийж байдаг.  

Paint үзэгдэл нь PaintEventHandler төлөөлөгчөөр боловсруулагддаг: 

Paint += new PaintEventHandler(this.Form_Paint);  private void Form_Paint(object sender,      System.Windows.Forms.PaintEventArgs e) {       }  

PaintEventHandler төлөөлөгч нь PaintEventArgs параметрийг хүлээж авдаг, энэ параметр нь дараахь 2 чухал пропертиг агуулдаг: 

• Graphics – Зуралт хийх Graphics төрлийн объектыг буцаана • ClipRectangle  ‐ Зуралт хийгдэх тэгш өнцөгт муж 

Graphics  класс нь шулуун,  текст болон дүрсүүдийг  зурахад зориулагдсан олон тооны методуудыг агуулна. 

Page 103: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐103‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

4.2.1 Текст зурах 

Консоль  програмын  хувьд  Console.Write,  Console.WriteLine  методуудыг ашиглаад текстийг хэвлэдэг бол цонхтой програмын хувьд илүү олон мэдээлэл шаарддаг. 

Цонхон дээр текст зурахад DrawString методыг ашигладаг бөгөөд энэ методын 6 хувилбар байдаг. Эхний хэлбэр нь хамгийн энгийн бөгөөд текстийн байрлалыг заахад PointF бүтцийг ашигладаг: 

PointF textPoint = new PointF(12.0f, 12.0f); e.Graphics.DrawString(ʺText location specified by a PointF valueʺ,                        Font,                        SystemBrushes.WindowText,                        textPoint);  

Дараагийн хувилбар нь бодит тоон утгаар байрлалыг нь заах боломжтой: 

e.Graphics.DrawString(ʺText location specified by float valuesʺ,                        Font,                        SystemBrushes.WindowText,                        12.0f,                        12.0f);  DrawString методын дээрх хоёр хувилбар дээр урт текст зурах үед гарах асуудал гарна.  Дээрх  методууд  нь  нэг  мөр  текстийг  зурдаг  бөгөөд  текстийн  урт контролын  эсвэл  цонхны  мужаас  хэтэрсэн  үед  ирмэг  дээгүүр  хэтрэн  зуралт хийдэг. 

Гурав дахь хувилбар нь RectangleF  төрлийн утга дамжуулан текстийн зурагдах мужийг хязгаарлаж, текстийг тухайн мужид багтаан зурдаг: 

string crispinSpeech =      ʺWe few, we happy few, we band of brothers. ʺ +     ʺFor he today that sheds his blood with me ʺ +     ʺshall be my brother, be he neʹer so vile, ʺ +     ʺthis day shall gentle his condition. ʺ +     ʺAnd gentlemen in England now abed ʺ +     ʺshall think themselves accursed they were not here, ʺ +     ʺand hold their manhoods cheap whiles any speaks ʺ +     ʺthat fought with us upon Saint Crispinʹs day. ʺ;  RectangleF boundingRect = new RectangleF(12.0f,                                          100.0f,                                          180.0f,                                          180.0f); e.Graphics.DrawString(crispinSpeech,                       Font,                       SystemBrushes.WindowText,                       boundingRect);  

Page 104: Dotnet lekts

“.NET програмчлал” хичээлийн лекцийн хураангуй  

‐104‐                 Боловсруулсан багш ММЗТэнхимийн ахлах багш,  магистр Б.Болормаа 

Үлдсэн  гурван  хувилбар  нь  өмнөх  хувилбаруудтай  төстэй  бөгөөд  ялгаа  нь StringFormat  төрлийн  параметрийг  авдаг.  StringFormat  нь  текстийг  яаж байрлуулахыг  заана.  StringFormatFlags  тоочих  төрөл  нь  байрлуулах  утгуудыг агуулна. 

Утга  Тайлбар DirectionRightToLeft  Баруунаасаа зүүн тийш зурагдана DirectionVertical  Босоо чиглэлд зурагдана DisplayFormatControl  Тэмдэгтийг дүрслэх тусгай формат FitBlackBox   LineLimit   MeasureTrailingSpaces   NoClip   NoFontFallback   NoWrap