A C# nyelv bemutatása

A C# (más néven "See Sharp") egy modern, objektumorientált és típusbiztos programozási nyelv. A C# lehetővé teszi a fejlesztők számára, hogy sokféle biztonságos és robusztus alkalmazást készítsenek, amelyek a .NET-ben futnak. A C# a C nyelvcsaládban gyökerezik, és azonnal megismerkedik a C, a C++, a Java és a JavaScript programozókkal. Ez a bemutató áttekintést nyújt a nyelv főbb összetevőiről a C# 8-ban és a korábbi verziókban. Ha interaktív példákon keresztül szeretné megismerni a nyelvet, próbálja ki a C#-oktatóanyagok bemutatását .

A C# egy objektumorientált, összetevő-orientált programozási nyelv. A C# nyelvi szerkezeteket biztosít ezeknek a fogalmaknak a közvetlen támogatásához, így a C# természetes nyelvvé teszi a szoftverösszetevők létrehozását és használatát. A C# a kezdetek óta olyan funkciókkal bővült, amelyek új számítási feladatokat és új szoftvertervezési eljárásokat támogatnak. A C# lényege egy objektumorientált nyelv. Ön határozza meg a típusokat és azok viselkedését.

Számos C#-funkció segít robusztus és tartós alkalmazások létrehozásában. A szemétgyűjtés automatikusan felszabadítja a nem elérhető, nem használt objektumok által elfoglalt memóriát. A nullázható típusok védenek a lefoglalt objektumokra nem hivatkozó változók ellen. A kivételkezelés strukturált és bővíthető megközelítést biztosít a hibaészleléshez és a helyreállításhoz. A Lambda-kifejezések támogatják a funkcionális programozási technikákat. A Language Integrated Query (LINQ) szintaxisa közös mintát hoz létre az adatok bármely forrásból történő kezeléséhez. Az aszinkron műveletek nyelvi támogatása szintaxist biztosít az elosztott rendszerek létrehozásához. A C# egységes típusrendszerrel rendelkezik. Minden C#-típus, beleértve az olyan primitív típusokat is, mint az int és double, egyetlen gyökértípustól object öröklik. Minden típus közös műveletekből áll. A bármilyen típusú értékek tárolhatók, szállíthatók és kezelhetők konzisztens módon. A C# emellett a felhasználó által definiált referenciatípusokat és az értéktípusokat is támogatja. A C# lehetővé teszi az objektumok dinamikus lefoglalását és az egyszerűsített struktúrák soros tárolását. A C# támogatja az általános módszereket és típusokat, amelyek növelik a típus biztonságát és teljesítményét. A C# iterátorokat biztosít, amelyek lehetővé teszik a gyűjteményosztályok implementálói számára, hogy egyéni viselkedéseket határozzanak meg az ügyfélkódhoz.

A C# hangsúlyozza a verziószámozást , hogy a programok és a kódtárak idővel kompatibilis módon fejlődhessenek. A verziószámozási szempontok által közvetlenül befolyásolt C#-kialakítás jellemzői közé tartoznak a különálló virtual és override módosítók, a metódusok túlterhelésének feloldására vonatkozó szabályok és az explicit felülettag-deklarációk támogatása.

.NET-architektúra

A C#-programok .NET-en futnak, egy közös nyelvi futtatókörnyezetnek (CLR) nevezett virtuális végrehajtási rendszeren és osztálykódtárak készletén. A CLR egy nemzetközi szabvány, a közös nyelvi infrastruktúra (CLI) Microsoft általi implementálása. A parancssori felület a végrehajtási és fejlesztési környezetek létrehozásának alapja, amelyekben a nyelvek és kódtárak zökkenőmentesen működnek együtt.

A C# nyelven írt forráskód egy olyan köztes nyelvre (IL) van lefordítva, amely megfelel a CLI-specifikációnak. Az IL-kód és az erőforrások, például a bitképek és a sztringek, egy szerelvényben vannak tárolva, általában .dllkiterjesztéssel. A szerelvény egy jegyzékfájlt tartalmaz, amely információkat nyújt a szerelvény típusáról, verziójáról és kultúrájáról.

A C#-program végrehajtásakor a rendszer betölti a szerelvényt a CLR-be. A CLR igény szerinti (JIT) fordítással konvertálja az IL-kódot natív gépi utasításokká. A CLR az automatikus szemétgyűjtéssel, a kivételkezeléssel és az erőforrás-kezeléssel kapcsolatos egyéb szolgáltatásokat nyújt. A CLR által végrehajtott kódot néha "felügyelt kódnak" is nevezik. A "nem felügyelt kód" egy adott platformra irányuló natív gépi nyelvre van lefordítva.

A nyelvi együttműködés a .NET egyik fő funkciója. A C#-fordító által előállított IL-kód megfelel a Common Type Specification (CTS) szabványnak. A C#-ból létrehozott IL-kód az F#, Visual Basic, C++ .NET-verzióiból létrehozott kódokkal használható. Több mint 20 cts-kompatibilis nyelv létezik. Egyetlen szerelvény több modult is tartalmazhat, amelyek különböző .NET-nyelveken íródhatnak. A típusok úgy hivatkozhatnak egymásra, mintha ugyanazon a nyelven írták volna őket.

A futásidejű szolgáltatások mellett a .NET kiterjedt kódtárakat is tartalmaz. Ezek a kódtárak számos különböző számítási feladatot támogatnak. Névterekbe vannak rendezve, amelyek számos hasznos funkciót biztosítanak. A kódtárak a fájlbemenettől és a kimenettől kezdve a sztringkezelésen át az XML-elemzésig, a webalkalmazás-keretrendszereken át a Windows Forms vezérlőkig mindent tartalmaznak. A tipikus C#-alkalmazás a .NET-osztálytárat használja széles körben a gyakori "vízvezeték-" feladatok kezelésére.

A .NET-tel kapcsolatos további információkért lásd a .NET áttekintését.

Hello world

A "Hello, World" program hagyományosan egy programozási nyelv bemutatására szolgál. Itt van a C#-ban:

using System;

class Hello
{
    static void Main()
    {
        Console.WriteLine("Hello, World");
    }
}

A "Hello, World" program egy using olyan direktívával kezdődik, amely a System névtérre hivatkozik. A névterek hierarchikus eszközöket biztosítanak a C#-programok és -kódtárak rendszerezéséhez. A névterek típusokat és más névtereket tartalmaznak – például a System névtér számos típust tartalmaz, például a Console programban hivatkozott osztályt, valamint számos egyéb névteret, például IO és Collections. Egy using adott névtérre hivatkozó irányelv lehetővé teszi az adott névtér tagjait tartalmazó típusok nem minősített használatát. Az irányelv miatt using a program rövidítésként használhatja Console.WriteLine a System.Console.WriteLine.

A Hello "Hello, World" program által deklarált osztálynak egyetlen tagja van, a metódus neve Main. A Main metódus deklarálása a static módosítóval történik. Bár a példánymetódusok hivatkozhatnak egy adott objektumpéldányra a kulcsszó thishasználatával, a statikus metódusok egy adott objektumra való hivatkozás nélkül működnek. Konvenció szerint a C Main #-programok belépési pontja egy statikus metódus.

A program kimenetét a WriteLine névtérben lévő System osztály metódusa Console hozza létre. Ezt az osztályt a szabványos osztálykódtárak biztosítják, amelyekre alapértelmezés szerint a fordító automatikusan hivatkozik.

Típusok és változók

A típus a C#-ban lévő adatok struktúráját és viselkedését határozza meg. A típus deklarációja magában foglalhatja a tagokat, az alaptípust, az általa implementált interfészeket és az adott típushoz engedélyezett műveleteket. A változó egy adott típusú példányra hivatkozó címke.

A C#-ban kétféle típus létezik: értéktípusok és referenciális típusok. Az értéktípusok változói közvetlenül tartalmazzák az adataikat. A referenciatípusok változói az adataikra mutató hivatkozásokat tárolnak, az utóbbit objektumoknak nevezik. Referenciális típusok esetén két változó hivatkozhat ugyanarra az objektumra, és lehetséges, hogy az egyik változó műveletei hatással vannak a másik változó által hivatkozott objektumra. Az értéktípusok esetében a változók mindegyike saját adatmásolattal rendelkezik, és az egyiken végzett műveletek nem befolyásolhatják a másikat (kivéve ref a paraméterváltozókat).out

Az azonosító egy változó neve. Az azonosító unicode karakterek sorozata, szóköz nélkül. Az azonosító lehet egy C#-beli fenntartott szó, ha az előtagja @. A fenntartott szavak azonosítóként való használata hasznos lehet más nyelvekkel való interakciók során.

A C#értéktípusai tovább vannak osztva egyszerű típusokra, számtípusokra, struktúratípusokra, nullázható értéktípusokra és rekordértéktípusokra. A C#-referenciatípusok tovább vannak osztva osztálytípusokra, felülettípusokra, tömbtípusokra és delegálttípusokra.

Az alábbi vázlat áttekintést nyújt a C# típusrendszeréről.

A C#-programok típusdeklarációkat használnak új típusok létrehozásához. A típusdeklaráció megadja az új típus nevét és tagjait. A C# hat típuskategóriája felhasználó által definiálható: osztálytípusok, struktúratípusok, felülettípusok, enumerálási típusok, delegálttípusok és rekordértékek. Típusokat is deklarálhatrecord, vagy record structrecord class. A rekordtípusok fordító-szintetizált tagokkal rendelkeznek. A rekordokat elsősorban értékek tárolására használja, minimálisan társított viselkedéssel.

  • A class típus olyan adatstruktúrát határoz meg, amely adattagokat (mezőket) és függvénytagokat (metódusokat, tulajdonságokat és egyebeket) tartalmaz. Az osztálytípusok támogatják az önálló öröklést és a polimorfizmust, olyan mechanizmusokat, amelyekkel a származtatott osztályok kiterjeszthetik és specializálhatják az alaposztályokat.
  • A struct típus abban hasonlít az osztálytípusra, hogy adattagokkal és függvénytagokkal rendelkező struktúrát jelöl. Az osztályoktól eltérően azonban a struktúrák értéktípusok, és általában nem igényelnek halomfoglalást. A struktúratípusok nem támogatják a felhasználó által megadott öröklést, és minden struktúratípus implicit módon öröklődik a típustól object.
  • A interface típus nyilvános tagok nevesített halmazaként definiálja a szerződést. A class vagy struct a megvalósítónak interface biztosítania kell a felület tagjainak implementációit. Egy interface több alapillesztőtől öröklődhet, és egy class vagy struct több illesztőt is implementálhat.
  • A delegate típus egy adott paraméterlistával és visszatérési típussal rendelkező metódusokra mutató hivatkozásokat jelöl. A meghatalmazottak lehetővé teszik a metódusok változókhoz rendelhető és paraméterként átadott entitásokként való kezelését. A delegáltak hasonlóak a funkcionális nyelvek által biztosított függvénytípusokhoz. Hasonlóak a más nyelvekben található függvénymutatók fogalmához is. A függvénymutatóktól eltérően a delegáltak objektumorientáltak és típusbiztosak.

A class, struct, interfaceés delegate típusok mindegyike támogatja az általános típusokat, amelyek más típusokkal paraméterezhetők.

A C# bármilyen típusú egydimenziós és többdimenziós tömböt támogat. A fent felsorolt típusokkal ellentétben a tömbtípusokat nem kell deklarálni a használatuk előtt. Ehelyett a tömbtípusok úgy jönnek létre, hogy szögletes zárójelekkel ellátott típusnevet követnek. Az egydimenziós tömb például int[] a kétdimenziós intint[,] tömb, amely int[][] egydimenziós tömbökből vagy egydimenziós tömbökből álló egydimenziós tömb, vagy egy "szaggatott" tömbből állint.int

A null értékű típusok nem igényelnek külön definíciót. Minden nem null értékű típushoz Ttartozik egy megfelelő nullértékű típusT?, amely további értéket tartalmazhat. null Például egy olyan típus, int? amely bármilyen 32 bites egész számot vagy értéket nulltartalmazhat, és string? olyan típus, amely bármilyen string értéket nulltartalmazhat.

A C#típusrendszere egységes, így bármilyen típusú érték kezelhető object. A C# minden típusa közvetlenül vagy közvetve az object osztálytípusból származik, és object az összes típus végső alaposztálya. A referenciatípusok értékeit a rendszer objektumként kezeli, ha az értékeket típusként objecttekinti meg. Az értéktípusok értékeit a rendszer dobozoló és kicsomagolási műveletek végrehajtásával objektumként kezeli. Az alábbi példában egy int érték lesz átalakítva object újra és újra a következővé int: .

int i = 123;
object o = i;    // Boxing
int j = (int)o;  // Unboxing

Ha egy értéktípus értéke egy object hivatkozáshoz van rendelve, a rendszer egy "dobozt" foglal le az érték tárolására. Ez a mező egy hivatkozástípus példánya, és az érték ebbe a mezőbe lesz másolva. Ezzel szemben, ha egy object hivatkozás értéktípusra van állítva, ellenőrzi, hogy a hivatkozott object érték a megfelelő értéktípus doboza-e. Ha az ellenőrzés sikeres, a mezőben szereplő érték az értéktípusba lesz másolva.

A C#egységesített típusrendszere gyakorlatilag azt jelenti, hogy az értéktípusok "igény szerint" hivatkozásként object lesznek kezelve. Az egyesítés miatt a típust object használó általános célú kódtárak minden olyan típushoz használhatók, amely származik object, beleértve a referencia- és értéktípusokat is.

A C#-ban többféle változó létezik, például mezők, tömbelemek, helyi változók és paraméterek. A változók a tárolási helyeket jelölik. Minden változó olyan típussal rendelkezik, amely meghatározza, hogy milyen értékek tárolhatók a változóban az alább látható módon.

  • Nem null értékű értéktípus
    • A pontos típus értéke
  • Nullable value type
    • Egy null érték vagy egy ilyen típusú érték
  • object
    • Hivatkozás null , hivatkozás bármilyen típusú objektumra, vagy bármely értéktípus dobozolt értékére való hivatkozás
  • Osztály típusa
    • Hivatkozás null , az adott osztálytípus egy példányára mutató hivatkozás vagy az adott osztálytípusból származtatott osztálypéldányra mutató hivatkozás
  • Interfész típusa
    • Hivatkozás null , az adott illesztőtípust megvalósító osztálytípus egy példányára mutató hivatkozás, vagy egy olyan értéktípus dobozolt értékére mutató hivatkozás, amely megvalósítja ezt az interfésztípust
  • Tömb típusa
    • Hivatkozás null , hivatkozás az adott tömbtípus egy példányára vagy egy kompatibilis tömbtípus egy példányára
  • Delegálás típusa
    • Hivatkozás null vagy hivatkozás egy kompatibilis delegált típusú példányra

Programstruktúra

A C# fő szervezeti fogalmai a programok, névterek, típusok, tagok és szerelvények. A programok deklarálnak olyan típusokat, amelyek tagokat tartalmaznak, és névterekbe rendezhetők. Az osztályok, a szerkezetek és az interfészek példák a típusokra. A mezők, metódusok, tulajdonságok és események példák a tagokra. A C#-programok lefordításakor fizikailag szerelvényekbe vannak csomagolva. A szerelvények általában fájlkiterjesztéssel .exe rendelkeznek, vagy .dllattól függően, hogy alkalmazásokat vagy kódtárakat implementálnak.

Kis példaként vegyünk egy olyan szerelvényt, amely a következő kódot tartalmazza:

namespace Acme.Collections;

public class Stack<T>
{
    Entry _top;

    public void Push(T data)
    {
        _top = new Entry(_top, data);
    }

    public T Pop()
    {
        if (_top == null)
        {
            throw new InvalidOperationException();
        }
        T result = _top.Data;
        _top = _top.Next;

        return result;
    }

    class Entry
    {
        public Entry Next { get; set; }
        public T Data { get; set; }

        public Entry(Entry next, T data)
        {
            Next = next;
            Data = data;
        }
    }
}

Ennek az osztálynak a teljes neve .Acme.Collections.Stack Az osztály több tagot tartalmaz: egy mező neve_top, két metódus és PopPush egy beágyazott osztály neveEntry. Az Entry osztály további három tagot tartalmaz: egy tulajdonságot, Nextegy elnevezett Datatulajdonságot és egy konstruktort. Ez Stack egy általános osztály. Egy típusparaméterrel rendelkezik, T amelyet a használat során egy konkrét típus vált fel.

A verem egy "first in - last out" (FILO) gyűjtemény. A rendszer új elemeket ad hozzá a verem elejéhez. Egy elem eltávolításakor az el lesz távolítva a verem tetejéről. Az előző példa deklarálja azt a Stack típust, amely meghatározza a tárolót és a verem viselkedését. Deklarálhat egy változót, amely egy ilyen típusú példányra hivatkozik a Stack funkció használatához.

A szerelvények végrehajtható kódot tartalmaznak köztes nyelv (IL) utasítások formájában, és szimbolikus információkat metaadatok formájában. A végrehajtás előtt a .NET Common Language Runtime just-in-time (JIT) fordítója a szerelvényben lévő IL-kódot processzorspecifikus kódká alakítja.

Mivel a szerelvény kódokat és metaadatokat egyaránt tartalmazó, önleíró funkcióegység, nincs szükség irányelvekre és fejlécfájlokra #include a C#-ban. Az adott szerelvényben található nyilvános típusok és tagok egyszerűen az adott szerelvényre való hivatkozással érhetők el egy C#-programban a program összeállításakor. Ez a program például a Acme.Collections.Stack szerelvény osztályát acme.dll használja:

class Example
{
    public static void Main()
    {
        var s = new Acme.Collections.Stack<int>();
        s.Push(1); // stack contains 1
        s.Push(10); // stack contains 1, 10
        s.Push(100); // stack contains 1, 10, 100
        Console.WriteLine(s.Pop()); // stack contains 1, 10
        Console.WriteLine(s.Pop()); // stack contains 1
        Console.WriteLine(s.Pop()); // stack is empty
    }
}

A program lefordításához hivatkoznia kell a korábbi példában definiált veremosztályt tartalmazó szerelvényre.

A C#-programok több forrásfájlban is tárolhatók. A C#-programok lefordításakor az összes forrásfájl együtt lesz feldolgozva, és a forrásfájlok szabadon hivatkozhatnak egymásra. Elméletileg olyan, mintha az összes forrásfájlt egyetlen nagy fájlba fűzték volna össze a feldolgozás előtt. A C#-ban soha nincs szükség továbbítási deklarációkra, mert néhány kivételtől eltekintve a deklarációs sorrend jelentéktelen. A C# nem korlátozza a forrásfájlt arra, hogy csak egy nyilvános típust deklaráljon, és nem követeli meg a forrásfájl nevét a forrásfájlban deklarált típusnak megfelelően.

A bemutató további cikkei ismertetik ezeket a szervezeti blokkokat.