Grafikus C# – Windows Forms tanfolyam › 14.1 lecke

Windows Forms · 14.1 lecke · build

Debug és Release változat

Eddig a programodat a Visual Studióban, Debug módban futtattad: a hibakereső csatlakozott, a töréspontok működtek. De ha a programot másnak szánod, nem a Debug változatot adod át, hanem a Release változatot: gyorsabb, kisebb, és nem tartalmaz fejlesztői segédleteket. A két változat nem pontosan ugyanúgy viselkedik, ezért tudnod kell a különbségeket, és a kiadás előtt a Release változatot is ki kell próbálnod. Ebben a leckében megtanulod a két konfiguráció különbségét (optimalizálás, PDB fájl, DEBUG konstans, Debug.Assert), a platformcélt (Any CPU, x64), a kimeneti mappákat, és hogyan fordítasz parancssorból (dotnet build -c Release).

  • kb. 90 perc
  • közepes szint
  • build
Diáklány C# programot készít laptopon

A lecke végére

  • megkülönbözteted a Debug és a Release konfigurációt, és tudod, melyiket mire használod;
  • ismered a különbségeket: optimalizálás, .pdb fájl, DEBUG konstans, Debug.* és Assert;
  • beállítod a konfigurációt a projekt tulajdonságaiban és a .csproj fájlban;
  • megérted a platformcélt (Any CPU, x86, x64);
  • megtalálod a kimeneti mappát (bin\Debug, bin\Release);
  • parancssorból is fordítasz (dotnet build -c Release), és kiadás előtt a Release változatot teszteled.

Mielőtt elkezded

Ehhez a leckéhez a 13. fejezet (hibakeresés, naplózás, Debug.Assert) szükséges.

13.10 Hibás alkalmazás javítása →

Mi a különbség a Debug és a Release között?

TulajdonságDebugRelease
CélFejlesztés és hibakeresés.Kiadás: a végfelhasználónak.
OptimalizálásKikapcsolva: a kód úgy fut, ahogy leírtad (lépegethető).Bekapcsolva: a fordító átrendezi, egyszerűsíti a kódot (gyorsabb, de nehezebb lépegetni).
SebességLassabb.Gyorsabb (gyakran 2–10-szeres a számításigényes részeken).
Szimbólumok (.pdb)Teljes: töréspontok, sorszámok.Alapból kevesebb vagy portable PDB: a stack trace sorszámokkal, de nehezebb lépegetni.
DEBUG konstansDefiniálva: #if DEBUG ágak, Debug.WriteLine, Debug.Assert, [Conditional("DEBUG")] hívások benne vannak.Nincs definiálva: ezek a kódrészek és hívások kikerülnek a programból.
TRACE konstansDefiniálva.Definiálva (a Trace.* megmarad).
Kimeneti mappabin\Debug\net8.0-windows\bin\Release\net8.0-windows\
Miért gyorsabb a Release?Az optimalizáló kiküszöböli a felesleges műveleteket, a kis metódusokat beépíti a hívás helyére (inlining), a változókat regiszterben tartja. Ez jó a sebességnek, de a hibakeresésnél zavaró: a változók „eltűnnek”, a sorok sorrendje változhat.
A Debug.* eltűnikA Debug.WriteLine, Debug.Assert és a [Conditional("DEBUG")] metódusok hívásai Release-ben ki sem fordulnak (13.7 lecke): nincs költségük, de a hatásuk sincs. Ami ezektől függött (például egy Assert védte feltétel), Release-ben nem védett.
Viselkedés-különbségekRitkán, de előfordul, hogy a program Debug-ban jó, Release-ben hibás: inicializálatlan vagy időzítés-függő kód (szálak), lebegőpontos kerekítési eltérés, Debug.Assert mellékhatással. Ezért a kiadás előtt a Release változatot tesztelni kell (13.8 lecke).
Melyiket mikor?Napi fejlesztés, hibakeresés: Debug. Sebességmérés (13.9 lecke), teszt a kiadás előtt, átadás: Release. Soha ne mérj teljesítményt Debug-ban.

Jósolj!

A programban Debug.Assert(lista.Count > 0); védi a kódot, a lista pedig valamiért üres. Mi történik Debug-ban, és mi Release-ben?

Jóslat ellenőrzése

Debug-ban az Assert felugró ablakkal jelzi a hibát (a hibakereső megállhat). Release-ben a sor kimarad: a program tovább fut, és később (például lista[0]) ArgumentOutOfRangeException-nel áll le, vagy rossz eredményt ad. A felhasználói és környezeti feltételt valódi ellenőrzéssel védd (13.5 lecke).

Konfiguráció kiválasztása és beállítása

Visual Studio: a konfiguráció kiválasztásamenü
Eszköztár: [ Debug ▼ ]  [ Any CPU ▼ ]  ▶ Start
Debug ← fejlesztés, hibakeresés
Release ← kiadás
Configuration Manager... ← konfigurációk és platformok kezelése

Projekt tulajdonságok (Project → Properties → Build):
Optimize code (Release: bekapcsolva)
Define DEBUG constant (Debug: bekapcsolva)
Debug symbols (Full / Portable / None)
Treat warnings as errors (opcionális, szigorúbb kód)
Platform target (Any CPU / x86 / x64)
Diaknyilvantarto.csproj (SDK-stílusú projekt)XML
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<Nullable>enable</Nullable>
</PropertyGroup>

<!-- csak Debug konfigurációban -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
</PropertyGroup>

<!-- csak Release konfigurációban -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>portable</DebugType>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <!-- kiadáskor a figyelmeztetés is hiba -->
</PropertyGroup>

</Project>
A .csprojA projektfájl (.csproj) XML: itt él minden build-beállítás. A Visual Studio tulajdonságablaka ezt szerkeszti; kézzel is módosítható (jobb klikk a projekten → Edit Project File). A Condition attribútum az adott konfigurációra korlátozza a beállítást.
DebugTypeA full / portable a .pdb fájl formátuma; a none nem készít szimbólumfájlt. A PDB nélkül a stack trace-ben nincsenek sorszámok. Kiadásnál tartsd meg a PDB-t (a hibák felderítéséhez), de nem kell telepíteni a felhasználónak.
OptimizeAz Optimize bekapcsolása a legnagyobb sebesség-különbség forrása. A Debug-ban kikapcsolt: a hibakereső ettől tud pontosan lépegetni.
Régi (.NET Framework) projektAz SDK-stílus előtti projektek .csproj fájlja hosszabb, de ugyanazok a beállítások (Optimize, DebugType, DefineConstants) találhatók benne, konfigurációnként.

Jósolj!

A Release konfigurációban TreatWarningsAsErrors igaz. A projektben van egy használatlan változó (CS0168 figyelmeztetés). Mi történik Release fordításkor, és mi Debug-ban?

Jóslat ellenőrzése

Release-ben a figyelmeztetés hibává válik: a fordítás megáll, amíg ki nem javítod; Debug-ban csak figyelmeztetés marad. Ez kényszeríti ki a tiszta kódot a kiadás előtt (13.1 lecke).

Platformcél és kimeneti mappák

PlatformcélJelentése
Any CPUA program a futtató gép architektúrájának megfelelően fut (64 bites gépen 64 bitesként). Az alapértelmezés, a legtöbb programnál elég.
x64Mindig 64 bites; csak 64 bites Windowson fut.
x86Mindig 32 bites; 32 és 64 bites Windowson is fut (kompatibilitás régi 32 bites DLL-ekkel).
A projekt mappái fordítás utánmappák
Diaknyilvantarto\
Diaknyilvantarto.csproj
Form1.cs, Program.cs ...
obj\ (köztes fájlok, ne nyúlj hozzá)
bin\
Debug\net8.0-windows\ Diaknyilvantarto.exe, .dll, .pdb
Release\net8.0-windows\ Diaknyilvantarto.exe, .dll, .pdb (ezt adod át, PDB nélkül)
Platform és DLL-ekHa a programod 32 bites natív DLL-t használ, a platformcélnak is x86-nak kell lennie, különben BadImageFormatException keletkezik. Egyszerű programnál az Any CPU a jó választás.
bin és objA bin a kész program mappája, az obj a köztes fájloké. Mindkettő generált: verziókezelésben (Git) nem tárolod (.gitignore), és bármikor törölhető (Clean).

Fordítás parancssorból

Terminál a projekt mappájában (dotnet SDK)parancsok
dotnet build                      (Debug fordítás)
dotnet build -c Release (Release fordítás)
dotnet clean -c Release (a Release köztes és kimeneti fájlok törlése)
dotnet build -c Release -o out (a kimenet az out mappába)
dotnet run -c Release (fordítás és indítás Release módban)
dotnet --info (a telepített SDK és futtatókörnyezetek)
Miért hasznos?A parancssori fordítás ugyanazt adja, mint a Visual Studio, de automatizálható (szkript, automatikus build-rendszer), és Visual Studio nélkül is működik. A kimenet végén az összefoglaló: hány figyelmeztetés és hiba volt.
Ellenőrzés kiadás előttKiadás előtt érdemes Clean után újrafordítani Release módban, a tiszta mappából: így nem marad benne régi fájl, és kiderül, ha valami csak a saját gépeden működött.

Jósolj!

Lefuttatod a dotnet build parancsot, majd megkeresed a programot a bin\Release mappában. Mit találsz?

Jóslat ellenőrzése

Semmit (vagy régi fájlt): a dotnet build alapból Debug konfigurációt fordít, a kimenet a bin\Debug mappába kerül. Release-hez a -c Release kapcsoló kell.

📷 Képernyőkép helye

Mit tegyél ide: a Visual Studio konfiguráció-választója (Debug/Release) és a bin mappa két változattal.Javasolt fájlnév: winforms-14-1-konfiguracio.webp · Alt szöveg: A Debug és Release konfiguráció kiválasztása

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. Debug-ban jó, Release-ben nem

A program a saját gépen fut, a Release változat hibás eredményt ad.

Ok és javítás

Gyakori ok: egy Debug.Assert vagy [Conditional("DEBUG")] hívás mellékhatása hiányzik, vagy inicializálatlan/szálfüggő kód. Keress a Debug.* hívásokban mellékhatást, és a naplót nézd (13.7 lecke).

2. A töréspont Release-ben nem áll meg

A töréspont halvány, vagy furcsa helyen áll meg.

Ok és javítás

Az optimalizált kód nem felel meg sor-soronként a forrásnak. Hibakereséshez Debug konfiguráció kell; Release-hibát naplóval és a stack trace-sel keress.

3. A bin\Release üres

A dotnet build után nincs Release kimenet.

Ok és javítás

A parancs Debug-ot fordított. dotnet build -c Release, vagy a Visual Studio-ban a konfigurációt Release-re állítva (Build → Build Solution).

4. BadImageFormatException a másik gépen

A program a fejlesztő gépen fut, a másikon nem indul.

Ok és javítás

Platformcél-eltérés (például x86 program 64 bites natív DLL-lel, vagy fordítva). Egyeztesd a platformot a használt natív könyvtárakkal.

5. A Release nem fordul

Debug-ban lefordul, Release-ben leáll hibával.

Ok és javítás

Valószínűleg TreatWarningsAsErrors: egy figyelmeztetés hibává vált. Az Error List mutatja; javítsd a figyelmeztetést (13.1 lecke).

6. A stack trace-ben nincs sorszám

A hibaüzenetben a metódus látszik, de a sor nem.

Ok és javítás

Nincs .pdb a program mellett (vagy DebugType=none). Tartsd meg a PDB-t a kiadás mellett a hibakereséshez.

Mini projekt: Debug–Release összehasonlító

Készíts egy kis programot, amely önmagáról megmondja, milyen módban fordították, és mérd meg a két változat különbségét:

  1. Projekt: Windows Forms (BuildDemo); lblMod, btnMeres (Prímszámolás), btnAssert (Assert próba), lblEredmeny, lblHivasok, lblAssert.
  2. Kód: másold be a lenti kódot (módkijelzés #if DEBUG-gal, [Conditional] számláló, mérés Stopwatch-csal, Debug.Assert).
  3. Debug futtatás: Debug konfigurációban indítsd (Ctrl+F5, hibakereső nélkül), a prímszámolást kattintsd 5-ször, jegyezd fel a mediánt.
  4. Release futtatás: váltsd Release-re, fordítsd újra (Rebuild), indítsd, és mérd ugyanúgy.
  5. Assert próba: mindkét módban kattints az Assert próba gombra; írd le, mi történik (felugró ablak? tovább fut?).
  6. Fájlok: hasonlítsd össze a bin\Debug és bin\Release mappát: az .exe, .dll, .pdb mérete.
  7. csproj: add a Release-hez a TreatWarningsAsErrors beállítást, szúrj be egy használatlan változót, és figyeld meg a Debug és Release különbségét.
  8. Parancssor: fordítsd dotnet build -c Release -o out paranccsal, és indítsd az out mappából.
  9. Jelentés: táblázat: szempont, Debug, Release (mód felirat, számláló értéke, medián idő, Assert viselkedése, fájlméretek), és 3–4 mondatos tanulság.
A kód és az elvárt különbségek (próbáld ki előbb önállóan!)
Form1.cs (using System.Diagnostics;)C#
private static int hivasok;

private static string Mod()
{
#if DEBUG
return "DEBUG";
#else
return "RELEASE";
#endif
}

[Conditional("DEBUG")]
private static void Szamol() { hivasok++; } // Release-ben a hívás ki sem fordul

private static bool Prim(int n)
{
for (int d = 2; d * d <= n; d++) { if (n % d == 0) { return false; } }

return true;
}

private void Form1_Load(object sender, EventArgs e)
{
lblMod.Text = "Fordítási mód: " + Mod() + " (hibakereső csatlakozva: " + Debugger.IsAttached + ")";
}

private void btnMeres_Click(object sender, EventArgs e)
{
hivasok = 0;

Stopwatch sw = Stopwatch.StartNew();
int db = 0;

for (int i = 2; i < 3000000; i++) { Szamol(); if (Prim(i)) { db++; } }

sw.Stop();
lblEredmeny.Text = "Prímek: " + db + ", idő: " + sw.ElapsedMilliseconds + " ms";
lblHivasok.Text = "A Szamol() hívásainak száma: " + hivasok;
}

private void btnAssert_Click(object sender, EventArgs e)
{
Debug.Assert(false, "Szándékos Assert-hiba"); // Debug: felugró ablak; Release: kimarad
lblAssert.Text = "Az Assert után a program fut tovább (" + DateTime.Now.ToString("HH:mm:ss") + ")";
}

Várható különbségek: a mód felirat DEBUG / RELEASE; a hívásszámláló Debug-ban kb. 3 millió, Release-ben 0; a prímszámolás Release-ben általában érezhetően gyorsabb; az Assert csak Debug-ban ad felugró ablakot; a bin\Debug mappa fájljai tipikusan nagyobbak. A számok gépfüggők: a saját méréseidet jegyezd fel.

📷 Képernyőkép helye

Mit tegyél ide: a program két módban, egymás mellett (felirat, számláló, idő).Javasolt fájlnév: winforms-14-1-kesz.webp · Alt szöveg: A Debug–Release összehasonlító

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Saját program Release-ben

Fordítsd Release módban egy korábbi projektedet, és futtasd végig a tesztlistáját. Találsz különbséget?

Egy lehetséges megoldás

Nézd meg a naplót és a hibaüzeneteket; különösen a Debug.Assert-re épülő ellenőrzések, az időzítések és a szálak helyeit. Ha eltérést találsz, jegyezd fel hibajegyként (13.8 lecke).

2. Feltételes naplózás

Írj [Conditional("DEBUG")] metódust, amely csak Debug-ban naplóz a konzolra, és ellenőrizd Release-ben.

Egy lehetséges megoldás

A metódus void típusú, törzse Debug.WriteLine; Release-ben a hívás és az argumentumok kiértékelése is kimarad (mellékhatásos argumentum nem fut le).

3. Csak Release

Állítsd be, hogy a Release konfiguráció a figyelmeztetést hibának tekintse, a Debug pedig ne.

Egy lehetséges megoldás

A .csproj-ban a PropertyGroup Condition="'$(Configuration)' == 'Release'" blokkba <TreatWarningsAsErrors>true</TreatWarningsAsErrors>.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Melyiket adod át?

Debug vagy Release változatot adsz a felhasználónak?

Megoldás megnyitása

A Release változatot: gyorsabb, kisebb, nem tartalmaz fejlesztői segédleteket.

2. Hol a kimenet?

Melyik mappában találod a Release programot?

Megoldás megnyitása

A bin\Release\<keretrendszer>\ mappában (például net8.0-windows).

Közepes szint

3. Mi tűnik el?

Mi tűnik el Release fordításban?

Megoldás megnyitása

A Debug.* hívások, a [Conditional("DEBUG")] metódushívások és a #if DEBUG kódrészletek.

4. Platform

Mikor kell x86 platformcél?

Megoldás megnyitása

Ha a program 32 bites natív DLL-t használ; egyébként az Any CPU megfelelő.

Kihívás szint

5. Egy gép, két változat

Miért kell kiadás előtt Release-ben is tesztelni?

Megoldás megnyitása

Mert az optimalizálás és a kimaradó Debug.* kód miatt a viselkedés eltérhet; a felhasználó a Release változatot használja.

6. Tiszta build

Miért érdemes kiadás előtt Clean és Rebuild?

Megoldás megnyitása

Hogy ne maradjon régi köztes fájl, és kiderüljön, ha valami csak a saját gépen működött.

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mi az optimalizálás?

A fordító átrendezi és egyszerűsíti a kódot a sebességért (Release-ben).

2. Mi a PDB?

A hibakereső szimbólumfájl: sorszámokat és töréspontokat tesz lehetővé.

3. Mi a DEBUG konstans?

Debug-ban definiált; a #if DEBUG és a Debug.* ettől függ.

4. Mit jelent az Any CPU?

A program a gép architektúrájának megfelelően fut (64 bites gépen 64 bitesként).

5. Hogyan fordítasz Release-t parancssorból?

dotnet build -c Release.

6. Hol a kimenet?

bin\Release\... mappában.

7. Mikor teszteled a Release-t?

Kiadás előtt: ez az, amit a felhasználó kap.

Mit tudsz már?

  • Megkülönbözteted a Debug és Release konfigurációt, és tudod, mikor melyiket használd.
  • Beállítod a konfigurációt a tulajdonságablakban és a .csproj fájlban.
  • Ismered a platformcélt és a kimeneti mappákat.
  • Parancssorból is fordítasz, és kiadás előtt a Release változatot teszteled.

Következő lecke: EXE, DLL, projekt- és kimeneti mappák

Mi van a kimeneti mappában, és mit kell átadni a felhasználónak.