Kihagyás

Bevezetés

A .NET architektúra elemei

.NET architektúra felépítése

A .NET-re nyelvek és implementációk nagy családjaként érdemes tekinteni. A .NET Standard egy API gyűjtemény, ami az alapját adja a .NET implementációknak. Négy fontosabb implementációról beszélhetünk, a .NET Core-ról (már csak .NET), .NET Frameworkről (deprecated), a Mono-ról és az UWP-ről.

A Mono kis futásidejű alkalmazások fejlesztésére szolgál, segítségével Xamarin alkalmazások készíthetők pl. Androidra, iOS-re és Mac-re.

Az UWP (Universal Windows Platform) különböző platformokat támogató alkalmazások fejlesztését teszi lehetővé, pl. személyi számítógép, tablet, telefon, XBox. A platformok közös jellemzője, hogy Windows operációs rendszert futtatnak.

.NET Core és .NET Framework

A Framework egy 2002 óta létező .NET implementáció, amit a mai napig rengetegen használnak. Ez egy platformfüggő megvalósítás, elsősorban Windows asztali alkalmazások fejlesztésére optimalizálva Windows Forms és WPF segítségével, de webes alkalmazások is készíthetők a segítségével.

A Core egy már platformfüggetlen open source megvalósítás, Windowson, Linuxon és macOS-en is fut. Támogatja az UWP-t, WinForms-t és a WPF-et is, emellett az ASP.NET Core segítségével webes alkalmazások készíthetők. A Microsoft az utóbbi időben a nyílt forráskódú fejlesztés irányába fordult, ennek hatásaként a .NET Core megtalálható GitHubon.

Jelenleg a .NET 7.0 stabil verziónál tart a technológia.

Hello World

Hozzunk létre egy .NET Core konzolos alkalmazást, amely komplex módon írja ki a Hello World szöveget. Ez egy sablon alkalmazás, melyet elkészít a fejlesztőkörnyezet, segítségével áttekinthető a .NET-es projektek felépítése.

Alkalmazás konzolból

Először nézzük meg hogyan hozhatjuk létre az alkalmazást konzolból (A parancsok Windows CMD-ből vannak tesztelve, de Unix alapú rendszeren is működnie KELL).

  1. Hozz létre egy Hello nevű mappát és lépj bele.
1
2
3
$ cd <alkfejl> # egy random mappa, ahova szeretnéd pakolászni a gyakorlat dolgait.
$ mkdir Hello # az elozo mappában létrehoz egy Hello nevu mappát.
$ cd Hello # belelép a Hello mappába.
  1. Készítsd el a projektet a következő parancs segítségével.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ dotnet new console
Welcome to .NET 5.0!
---------------------
SDK Version: 5.0.400
...
Getting ready...
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on <alkfejl>\hello.csproj...
  Determining projects to restore...
  Restored <alkfejl>\hello.csproj (in 100 ms).
Restore succeeded.

A Hello mappában most két fájl látható: Program.cs és Hello.csproj.

  1. Fordítsd le a projektet futtatható állapotba.

Ahhoz, hogy egy .NET-es projekt fusson, le kell fordulnia (pont úgy, mint a C, C++, Java nyelveknek, amikkel már találkoztatok).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ dotnet build
Microsoft (R) Build Engine version 16.11.0+0538acc04 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  hello ->  <alkfejl>\bin\Debug\net5.0\hello.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:03.50

Az első két sort ignorálni lehet jelen pillanatban. Ezután a fordítóprogram (és környezete) meghatározza milyen projekteket kell visszaállítani (később), majd látható egy útvonal a Hello -> után. Ebből megsejthető, hogy Debug build készült és a végtermék egy dll fájl. Debug buildek során a fordítóprogram nem optimalizálja a forráskódot, így az alkalmas marad hibakeresési feladatok megoldására.

A log utolsó pár sora tájékoztat, hogy sikeres volt a fordítás (hisz nem is rontottunk el semmit még).

  1. Futtatás
1
2
$ dotnet run
Hello World!

A parancs kiadása után a Hello World! szövegnek kell megjelennie és egy soremelésnek. Amennyiben a build parancsot kihagyjuk, úgy a run elvégzi azt. Kipróbálható úgy, hogy a bin mappát kézzel kitöröljük és újrafuttatjuk a dotnet run parancsot.

Ugyanez Visual Studioval

Indítsunk egy Visual Studio-t és nézzük meg ugyanezeket a lépéseket itt.

  1. Válasszuk ki a kezdőoldalon Create a new project menüpontot

Új projekt létrehozása

1.2. Ha nem látunk ilyen lehetőséget, válasszuk ki a File > New > Project menüpontot

  1. A project template oldalon válasszuk ki a Console App (.NET Core) lehetőséget és kattintsunk a Next gombra

A projekt típusának kiválasztása

  1. A következő oldalon nevezzük el a projektünket és kattintsunk a Create gombra.

Alapbeállításként a C:\Users\<user>\source\repos mappába helyezi el a létrehozott projekteket. Itt lehetőség van még átállítani. Két név beállítására is lehetőség van, az első a projekt, a második pedig a Solution. Egy Solution alá több projekt is tartozhat.

Konfigurálás

A projekt felépítése

Solution

A Visual Studioban vizsgálva a projektet látható hogy a Hello2 projekt egy ugyanilyen nevű Solutionben szerepel. A solution úgy képzelhető el, mint egy konténer, mely több projektet tartalmazhat, illetve az egyes projektekhez közvetlenül nem tartozó (+ több projekt által is felhasznált) fájlokat tartalmazza.

Egy solution fájl kiterjesztése .sln. Ezt betöltve a solutionban lévő minden projekt betöltődik a fejlesztői környezetbe.

Solution Explorer

A Solution Explorer alapértelmezetten az egyik oldalon meg van nyitva, viszont ha véletlen bezárjátok: (fent) View -> Solution Explorer és újra megnyílik.

Project

Esetünkben van egy Hello2.csproj kiterjesztésű projekt fáj, ami a projekt szükséges függőségeit tartalmazza. A .csproj fájlt a VS arra használja hogy az oldalsó Solution Explolerben megjelenítse a projekteket. A projekt fájl tartalmát VS-ben a projekt Unload-olása után tudjuk megtekinteni, bármilyen más szövegszerkesztővel enélkül is megtekinthető.

A Hello2.csproj tartalma:

1
2
3
4
5
6
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
</Project>

Program.cs

A Program.cs megnyitása után látható, hogy gyakorlatilag kész van a Hello World alkalmazás. Ez egy alapértelmezett sablon, ami létrejön egy teljesen üres .NET Core alkalmazás létrehozásánál.

Maga a Program.cs tartalmazza az alkalmazás belépési pontját, ami a már ismerős Main metódus. Jelenleg kiírja a Hello World! szöveget és egy soremelést a (System.)Console.WriteLine segítségével.

Hierarchia szempontjából fontos, hogy az osztályok névterekbe vannak sorolva. Java alkalmazásoknál már megszokott, hogy az osztályok package-ekbe vannak rendezve, C# esetén ugyanerre a namespace-k vannak használva (mint C++ esetén).

Névterek a namespace kulcsszó segítségével definiálhatók. Amennyiben egy létező névteret szeretnénk valahol használni, azt a using kulcsszó segítségével tehetjük meg. Ez megfelel a Java import kulcsszó működésének, azzal a különbséggel, hogy amíg Java-ban létrejön a fájlrendszerben a névtérhierarchia, addig C#-ban nem.

Futtatás, fordítás

A projektet fordítani a Build menüpont alatt, vagy a Solution Explorerben a projektre jobb gombbal kattintva a szintén Build menüpont segítségével tehetjük meg.

Fordítás

Futtatni az F5 gombbal vagy a menüsorban található zöld nyíllal tudunk.

Futtatás

Egy cmd.exe ablak jelenik meg, ahol az első sorban látható a Hello World! szöveg, majd némi információ a környezetről. Ha ez az ablak csak egy pillanatig él és be is zárul, akkor ez a Console.ReadKey(); sor beszúrásával kiküszöbölhető.

Egészítsük ki a kódot:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
using System;

namespace Hello2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            string stg = Console.ReadLine();
            Console.WriteLine($"Your answer: {stg}");
        }
    }
}

A Console névtérben található minden, ami a konzolra íráshoz és onnan olvasáshoz szükséges. A ReadLine metódus addig olvassa a felhasználó által beírt szöveget a konzolról, míg újsort (entert) nem kap. Ezután a WriteLine függvény kiírja a paraméterben kapott szöveget és egy soremelést.

NuGet csomagkezelő rendszer

A NuGet a .NET csomagkezelő rendszere. Lehetővé teszi újrafelhasználható kódok csomagokba szervezését és megosztását. Az alkalmazás írója egy galériában tud keresni és válogatni az elérhető (és kompatibilis) csomagok közül.

A vállalatok nem mindig szeretnék megosztani a drága pénzért megírt csomagjaikat, melyeket csak cégen belül szeretnének felhasználni, ezért a publikusan elérhető nuget.org mellett privát szervereket is lehet használni.

Amennyiben egy csomag telepítve lett a projektben, annak publikus API-ja elérhető a kódból. A telepítés során egy konfigurációs fájlba kerülnek az adatok, magukat az DLL-eket nem tartalmazza a projekt (így a kód-menedzsment könnyebb). Fordítás során a Visual Studio automatikusan (dotnet restore) letölti a hiányzó csomagokat (egyszer), melyek utána belefordulnak az alkalmazásba.

A csomagok írásakor lehetőség van további NuGet csomagok felhasználására, viszont a végfelhasználó elől ezen függőségek rejtve vannak. A csomag telepítésekor a csomagkezelő rendszer a függőségeket is telepíti és a projekt életciklusa során menedzseli azt.

A projekt, Visual Studio és NuGet verziótól függően két helyen található a konfigurációs fájl: packages.config vagy a projekt fájl <PackageReference> szekciójában. Az első megoldás mára már csak a kompatibilitás megtartásáért felel.

Csomagok telepítése és használata

A Solution Explorer-ben a projekt nevére jobb klikk és Manage NuGet packages....

Csomagkezelő megnyitása

Az Installed fül alatt találhatók a már feltelepített csomagok és a Browse fül alatt lehet keresni és telepíteni. A telepítés után a Project/Dependencies/NuGet alatt megjelenik az újonnan feltelepített csomag.

Csomagkezelő felülete

Telepítsük fel a Serilog.Sinks.Console nevű csomagot a GUI-n keresztül.

A Tools/NuGet Package Manager/Package Manager Console segítségével elérhető a konzolos változata is a csomagkezelőnek, amely segítségével a következőképp lehet csomagokat telepíteni: Install-Package Serilog.Sinks.Console. Több projekt esetén oda kell figyelni, hogy a Solution Explorer-ben melyik projekt van kiválasztva alapértelmezettként, mert oda fogja telepíteni a kért csomagot (vagy specifikálni kell a projektet Install-Package Serilog.Sinks.Console -ProjectName NuGet_test).

Miután a csomagok feltelepültek, a következő programmal ki is próbálható a funkcionalitása:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using Serilog;

namespace NuGet_test
{
    class Program
    {
        static void Main(string[] args)
        {
            var log = new LoggerConfiguration()
                .WriteTo.Console()
                .MinimumLevel.Debug()
                .CreateLogger();

            log.Debug("Hello World");
            log.Information("Hello World");
        }
    }
}

Futtatás után az alábbi kimenetet kellene látni:

1
2
[18:56:23 DBG] Hello World
[18:56:23 INF] Hello World

A logoló csomag formázza a kiírt szöveget. Először egy időpont látható, majd a logolás szintje és végül a kért információ.

A projektet leíró fájlt megtekintve látható, hogy bővült a csomag telepítése után.

1
2
3
<ItemGroup>
  <PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
</ItemGroup>

Törölni egy a projekthez telepített csomagot az Installed fül alatt lehet, vagy az Uninstall-Package paranccsal.

Hibakeresés

A szekció célja, hogy a hallgatók találkozzanak a fejlesztőkörnyezet által visszaadott hibaüzenetekkel és fel tudják kutatni a keletkezett hiba forrását.

Hozzunk létre egy új projektet a meglévő Solutionbe (solution jobb klikk -> new project, majd adjunk hozzá egy osztályt DummyClass néven. A projekt nevén jobb klikk és Add -> Class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
namespace Hello22
{
    class DummyClass
    {
        private int userInput;

        public DummyClass(int userInput)
        {
            this.userInput = userInput;
        }

        public double CalculateMagicNumber()
        {
            return 1024 / (userInput - 42);
        }
    }
}

Ezután a Program osztályban lévő Main függvényt egészítsük ki.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
namespace Hello22
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.Write("Írjon be egy számot: ");
                int userInput = int.Parse(Console.ReadLine());
                Console.WriteLine();

                var magician = new DummyClass(userInput);

                Console.Write("A kapott számból előálló mágikus szám: ");
                Console.WriteLine(magician.CalculateMagicNumber());
            }
        }
    }
}

Ez a kezdetleges program több hibát tartalmazhat, keressük meg ezeket debuggerrel. Az eszköz csak akkor használható, ha a fordítási mód Debug, mert Release módban az ehhez szükséges szimbólumok nem kerülnek bele a binárisba.

Alapértelmezetten nem ez a projekt indul el, hanem a Hello2. Ennek megváltoztatására jobb klikk a Hello22 projektre (vagy ahogy el lett nevezve) a Solution Explorerben -> Set as Startup Project.

Betű, mint a felhasználó inputja

42, mint a felhasználó inputja

Ilyen állapotban a fejlesztői környezet Autos ablakában megtekinthetők a blokkban látható változók, illetve a Call Stack is, azaz, hogy a program milyen úton jutott el a hibás állapotba.

Feladat: Javítsátok ki a hibákat, hogy szöveg vagy 42 során is jól működjön a program. Invalid input esetén írja ki, hogy Rossz input, csak egész számot vár a program. 42 esetén írja ki, hogy Nem támogatott mágikus szám. Tipp: try-catch, int.TryParse.

Breakpoint-ok

A szövegszerkesztő bal szélén van egy szürke csík (sötét téma esetén), a sorszámoktól balra. Itt minden futtatható sorra tehetünk úgynevezett breakpointot, azaz ha a program futása eléri a piros pontot, akkor megáll és láthatók lesznek a változók, a programozó kitalálhatja hogy hol lehet hiba (Sőt át is tudja írni a változók értékét.).

Breakpoint

Jelen állapotban lehetőség van léptetni soronként a programot a menüsorban található eskzözök segítségével.

Vezérlők

Balról indulva:

  • program futásának megállítása
  • program újraindítása
  • következő utasítás mutatása
  • Step-In: A következő utasításra ugrás. Ha ez függvényhívás, akkor a függvényhívás törzsébe lép.
  • Step-Over: A következő utasításra ugrás. Ha ez függvényhívás, akkor a törzsét lefuttatja és a jelenlegi kontextus következő utasításával folytatódik.
  • Step-Out: A következő utasításra ugrás. A jelenlegi függvényből kilépve (a függvény maradék törzsét lefuttatja és a függvényhívás helyét kapjuk meg).

Hasznos kulcsszavak és jelölések hibakeresés közben:

  • breakpoint: Megállítja a program futását azon a programsoron, ahová tettük. Ezután léptethető a program.
  • conditional breakpoint: Mint az előző, de valamilyen feltételnek teljesülnie kell (pl. userInput == 42).
  • exception: Az Exception osztály egy leszármazott típusú objektuma. Ismerősnek kell lennie Programozás I-II, illetve Alkalmazásfejlesztés I kurzusokból.
  • call stack: Amikor megáll a program futása, egy ablakban látható a hívási lánc, ahogyan a program futása eljutott a megállás pontig.
  • locals: Szintén a program álló helyzetben való analízisére használható, a megállási pontról elérhető objektumok állapotai láthatók itt.

További olvasnivaló


Utolsó frissítés: 2023-08-01 09:43:37