2018. szeptember 8., szombat

A Visual Studio keretrendszer

A híres “Hello World!” program elsőként Dennis Ritchie és Brian Kernighan “A C programozási nyelv” című könyvében jelent meg, és azóta szinte hagyomány, hogy egy programozási nyelv bevezetőjeként ezt a programot mutatják be.

MSIL/CIL

A “hagyományos” programnyelveken – mint pl. a C++ – megírt programok ún. natív kódra fordulnak le, vagyis a processzor számára – kis túlzással – azonnal értelmezhetőek. A .NET (akárcsak a Java) más úton jár, a fordító először egy köztes nyelvre (Intermediate Language) fordítja le a forráskódot. Ez a nyelv a .NET világában az MSIL, illetve a szabványosítás után a CIL (MICROSOFT/CommonIL) – különbség csak az elnevezésben van. Jogos a kérdés, hogy a két módszer közül melyik a jobb? Ha nagy általánosságban beszélünk, akkor a válasz az, hogy nincs köztük különbség. Igaz, hogy a natív nyelvek hardver-közelibbek és emiatt gyorsabbak tudnak lenni, viszont ez több hibalehetőséggel is jár, amelyek elkerülése a felügyelt környezetben kiegyenlíti az esélyeket.
Bizonyos területeken viszont egyik vagy másik megközelítés jelentős eltérést eredményezhet. Jó példa a számítógépes grafika, ahol a natív nyelvek vannak előnyben pont azért, mert az ilyen számításigényes 
feladathoz minden csepp erőforrást ki kell préselni a hardverből. Másfelől a felügyelt környezet a hatékonyabb memóriakezelés miatt jobban teljesít olyan helyzetekben, ahol nagy mennyiségű adatot mozgatunk a memórián belül (pl. számos rendező algoritmus ilyen).

FORDÍTÁS ÉS FUTTATÁS

A natív programok ún. gépi kódra fordulnak le, míg a .NET forráskódokból egy CIL nyelvű futtatható állomány keletkezik. Ez a kód a feltelepített .NET Framework –nek szóló utasításokat tartalmaz. Amikor futtatjuk ezeket az állományokat, először az ún. JIT (Just–In–Time) fordító veszi kezelésbe, és lefordítja őket gépi kódra, amit a processzor már képes kezelni.
Amikor “először” fordítjuk le a programunkat, akkor egy ún.
Assembly (vagy szerelvény) keletkezik. Ez tartalmazza a felhasznált, illetve megvalósított típusok adatait (ez az ún. Metadata), amelyek a futtató környezetnek szolgálnak információval (pl. osztályok szerkezete, metódusai, stb.). Egy Assembly egy vagy több fájlból is állhat, tipikusan .exe (futtatható állomány) vagy .dll (osztálykönyvtár) kiterjesztéssel.

BCL

A .NET Framework telepítésével a számítógépre kerül – többek között – a BCL (Base Class Library), ami az alapvető feladatok (fájl olvasás/ írás, adatbázis-kezelés, adatszerkezetek … stb) elvégzéséhez szükséges eszközöket tartalmazza. Az összes többi könyvtár (ADO.NET, WCF, stb…) ezekre épül.

A C# PROGRAMOZÁSI NYELV

A C# (ejtsd: szí-sárp) a Visual Basic mellett a .NET fő programozási nyelve. 1999 –ben Anders Hejlsberg vezetésével kezdték meg a fejlesztését.
A C# tisztán objektumorientált, típusbiztos, általános felhasználású nyelv. A tervezésénél a lehető legnagyobb produktivitás elérését tartották szem előtt. A nyelv elméletileg platform független (létezik Linux és Mac fordító is), de napjainkban a legnagyobb hatékonyságot a Microsoft implementációja biztosítja.


HELLO WORLD!

A File menüben kattintsunk a New Project menüpontra, ekkor a megjelenő ablakban kiválaszthatjuk a projekt típusát. A jegyzetben nagyrészt Console Application sablont fogunk használni, ezzel egy parancssorban futó programot hozhatunk létre.

Az OK gombra kattintva elkészül az első projektünk, a forráskód így néz ki:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Meglepően sok mindent látunk, ahhoz képest, hogy ez a program a világon semmit nem csinál. Menjünk sorjában, egyelőre különösebb magyarázat nélkül, a következő fejezetekben mindenre fény derül. Az első négy sorral azokat a névtereket jelöltük ki, amelyeket használni szeretnénk. Ebben az esetben a Visual Studio egy kicsit túlbuzgó volt, egyelőre az első sor is elég lett volna, de nyugodtan hagyjunk mindent, ahogy van, még nincs jelentősége.
A következő lépésben megadjuk a programunk névterét, ez alapértelmezés szerint az lesz, amit a New Project ablakban a Name mezőben megadtunk. 

A class Program sor az, ami egy kicsit ijesztő lehet a kezdő programozó számára. A C# tisztán objektumorientált nyelv, ami egyelőre azt jelenti számunkra, hogy bármit teszünk, azt csakis egy osztályon belül egy függvényben vagy metódusban tehetjük. Egy osztályt a class kulcsszóval vezetünk be, amely után az osztály nevét kell írnunk.
Ebben a pillanatban még nem kell ennél többet tudnunk az objektumorientált programozásról, de nemsokára ennek is eljön az ideje.


Nem maradt más hátra, mint a Main függvény. Ez nagyon fontos összetevője minden C# programnak, hiszen ez az alkalmazásunk belépési pontja, itt kezdődik el a futása. Minden C# programnak tartalmaznia kell egy Main nevű függvényt, ellenkező esetben le sem fordul.

Vizsgáljuk meg egy kicsit a fejlesztőeszközt is!

 
Bal oldalon a forráskódot láthatjuk, míg a jobb oldalt az ún. Solution Explorer foglalja el. Minden esetben, amikor egy projektet készítünk, egy ún. Solution jön létre. Egy Solution több projektet is tartalmazhat, jobb gombbal kattintva hozhatjuk elő a hozzá tartozó helyi menüt, amely segítségével újabb projektet készíthetünk.
Ugyanígy minden projekthez is tartozik ilyen menü, amellyel pl. új elemeket adhatunk hozzá. Látható, hogy egy „faszerű” szerkezetről van szó. A félkövér betűvel kiemelt projekt a StartUp elem, ez fog elindulni, ha futtatjuk a Solution-t. Tetszés szerint megváltoztathatjuk ezt a beállítást a kívánt projekt helyi menüjében (Set as StartUp project).
A projekteket „lenyitva” a hozzá tartozó fájlokat találjuk, illetve két mappát, amelyek speciális célt szolgálnak. A Properties mappa a programról tartalmaz metaadatokat, például a készítő nevét, az aktuális verziószámot stb. A References mappa pedig a projektben használt osztálykönyvtárakat sorolja fel. Ebből rögtön kétféle is van, a BCL-hez tartozó könyvtárak (alapbeállítás szerint) nem másolódnak be a program kimeneti mappájába, míg a külső könyvtárak igen. Új projekt létrehozásakor is több könyvtárat találunk, ezek közül egyelőre a System és System.Core nélkülözhetetlen.
Ahhoz, hogy a programunkat futtassuk, először le kell fordítanunk. Ezt a Build menüben található Build Solution paranccsal tehetjük meg. Ha több projektünk is van, egyenként is fordíthatunk a helyi menüből.
Amennyiben nem kapunk hibaüzenetet, illetve a bal alsó sarokban megjelenik a Build Succeeded felirat, akkor a programunk szintaktikailag helyes, megpróbálhatjuk futtatni.
Ehhez a Debug menü Start Debugging illetve Start Without Debugging parancsait kell használnunk. Ha a projekt a legutóbbi fordítás óta megváltozott, akkor automatikusan le is fordítja a programunkat a Visual Studio. Használhatunk gyorsbillentyűket is, F6 a fordítás, míg F5 a futtatás (és fordítás, ha szükséges). Végezetül szintén elérhetjük a célunk, ha a menüsorban található kis zöld fektetett háromszögre kattintunk.
Lépjünk tovább, egyelőre a Main függvényen belül fogunk tevékenykedni. Ahhoz, hogy elkészíthessük a programunkat, tudnunk kell, hogyan kezelhetjük a parancssort a programunkból. A .NET Framework BCL-e erre is kínál megoldást, a Console osztály lesz segítségünkre:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!!!");
            Console.ReadKey();
        }
    }
}

Örömmel tapasztalhatjuk, hogy a Console szó után tett pont előhozza a választható függvények listáját. Ezt a Visual Studio IntelliSense-nek hívja. Ha nem ajánlja fel a listát a fejlesztőeszköz, akkor elképzelhető, hogy a kódkiegészítés nincs bekapcsolva. A visszakapcsoláshoz a következőket kell tenni:

1. Tools menü -> Options

2. Ha nincs bejelölve a „Show All Settings” négyzet, akkor kapcsoljuk be!

3. Text Editor -> C# -> IntelliSense -> Legyen bejelölve a „Show completion list after a character is typed” feliratú négyzet!

A WriteLine függvény kiírja a parancssorba a paraméterként kapott szöveget, majd új sort nyit. Amennyiben szeretnénk ugyanabban a sorban maradni, használjuk a Console.Write függvényt!

A Console.ReadKey függvény feladata, hogy vár egy billentyűleütést a felhasználótól, mielőtt továbblépne a program. Miért van erre szükség? A legegyszerűbb, ha kipróbáljuk a programot nélküle. Amit látni fogunk, az egy villanás, hiszen a programunk csak annyit tesz, hogy kiír egy szöveget és kilép. Ez utóbbi miatt kellett valami, amivel megszakíthatjuk futását, és itt jön a képbe a ReadKey.

A C# SZINTAKTIKÁJAAmikor egy programozási nyelv szintaktikájáról beszélünk, akkor azokra a szabályokra gondolunk, amelyek megszabják a forráskód felépítését. Ez azért fontos, mert az egyes fordítóprogramok csak ezekkel a szabályokkal létrehozott kódot tudják értelmezni. Ha a forráskód szintaxisa nem megfelelő, a program nem fordul le.
A C# úgynevezett C-stílusú szintaxissal rendelkezik (azaz a C programozási nyelv szintaxisát veszi alapul), ez három fontos szabályt von maga után:

  • Az egyes utasítások végén pontosvessző - ; - áll.
  • A kis- és nagybetűk különböző jelentőséggel bírnak, azaz a “program” és “Program” azonosítók különböznek. Ha a fenti kódban Console.WriteLine helyett console.writeline –t írnánk, akkor a program nem fordulna le.
  • A program egységeit (osztályok, metódusok stb.) ún. blokkokkal jelöljük ki, kapcsos zárójelek ({ és }) segítségével.

KULCSSZAVAK
Szinte minden programnyelv definiál kulcsszavakat, amelyek speciális jelentőséggel bírnak a fordító számára. Ezeket az azonosítókat a saját meghatározott jelentésükön kívül nem lehet másra használni, ellenkező esetben a fordító hibát jelez. Vegyünk például egy változót, aminek az “int” nevet akarjuk adni! Az “int” név is beépített típusra utal, azaz kulcsszó, tehát nem fog lefordulni a program.

int int //hiba;

A legtöbb fejlesztőeszköz (így a Visual Studio is) megszínezi a kulcsszavakat, ezért könnyű elkerülni a fenti hibát.
A C# 5.0 már 77 kulcsszót ismer:

abstract default foreach object Sizeof unsafe as delegate goto operator stackalloc ushort
base do If out Static using bool double implicit override String virtualbreak else In params Struct volatile byte enum int private Switch void case event interface protected This while
catch explicit internal public Throw char extern Is readonly True checked false lock ref Try class finally long return Typeof const fixed namespace sbyte Uint continue float new sealed Ulong decimal for null short unchecked

Ezeken kívül létezik még 23 azonosító, amelyeket a nyelv nem tart fenn speciális használatra, de különleges jelentéssel bírnak. Amennyiben lehetséges, kerüljük a használatukat “hagyományos” változók, osztályok létrehozásánál: add equals group let Remove var ascending from in on Select where by get into orderby Set yield descending global join partial Value

Néhányuk a környezettől függően más-más jelentéssel is bírhat, a megfelelő fejezet bővebb információt ad majd ezekről az esetekről.

MEGJEGYZÉSEK

A forráskódba megjegyzéseket tehetünk. Ezzel egyrészt üzeneteket hagyhatunk (pl. egy metódus leírása) magunknak vagy a többi fejlesztőnek, másrészt a kommentek segítségével dokumentációt tudunk generálni, ami szintén az első célt szolgálja, csak éppen élvezhetőbb formában.
Megjegyzéseket a következőképpen hagyhatunk:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!!!");//egy sor
            Console.ReadKey();/* több
                               sor
                               ide*/
        }
    }
}

NÉVTEREK

A .NET Framework osztálykönyvtárai szerény becslés szerint is legalább tízezer nevet, azonosítót tartalmaznak. Ilyen nagyságrenddel elkerülhetetlen, hogy a nevek ne ismétlődjenek. Ekkor egyrészt nehéz eligazodni közöttük, másrészt a fordító sem tudná, mikor mire gondolunk. Ennek a problémának a kiküszöbölésére hozták létre a névterek fogalmát. Egy névtér tulajdonképpen egy virtuális doboz, amelyben a logikailag összefüggő osztályok, metódusok stb. vannak. Nyilván könnyebb megtalálni az adatbázis-kezeléshez szükséges osztályokat, ha valamilyen kifejező nevű névtérben vannak (pl. System.Data).


5 megjegyzés: