Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A kód hibáinak kijavítása időigényes és nem egyszer bosszantó feladat lehet. Időbe telik, mire megtanulja, hogyan lehet hatékonyan hibakeresést végezni. Egy olyan hatékony IDE, mint a Visual Studio, sokkal egyszerűbbé teheti a munkáját. Az IDE segít a hibák kijavításában és a kód gyorsabb hibakeresésében, valamint a jobb kód írásában kevesebb hibával. Ez a cikk átfogó képet nyújt a "hibajavítási" folyamatról, így megtudhatja, hogy mikor érdemes használni a kódelemzőt, mikor kell használni a hibakeresőt, hogyan lehet kijavítani a kivételeket, és hogyan kódolva a szándékot. Ha már tudja, hogy a hibakeresőt kell használnia, tekintse meg először a hibakeresőt.
Ebben a cikkben megtudhatja, hogyan használhatja az IDE-t a kódolási munkamenetek hatékonyabbá tételéhez. Több feladatot is érintünk, például:
A kód előkészítése hibakeresésre az IDE kódelemzőjének használatával
Kivételek (futásidejű hibák) kijavítása
A hibák minimalizálása szándékkódolással (érvényesség használatával)
Mikor érdemes használni a hibakeresőt?
Ezeknek a feladatoknak a bemutatásához bemutatjuk az alkalmazások hibakeresése során előforduló leggyakoribb hibák és hibák néhány típusát. Bár a mintakód C#, a fogalmi információk általában a C++, a Visual Basic, a JavaScript és a Visual Studio által támogatott egyéb nyelvekre vonatkoznak (kivéve, ha fel vannak jegyezve). A képernyőképek C#-ban találhatók.
Mintaalkalmazás létrehozása néhány hibával és problémával.
Az alábbi kód néhány hibát tartalmaz, amelyeket a Visual Studio IDE használatával kijavíthat. Ez az alkalmazás egy egyszerű alkalmazás, amely szimulálja a JSON-adatok egy műveletből való lekérését, az adatok objektumba való deszerializálását és egy egyszerű lista frissítését az új adatokkal.
Az alkalmazás létrehozásához a Visual Studio és a .NET asztali fejlesztési kiegészítő telepítése szükséges.
Ha még nem telepítette a Visual Studiót, lépjen a Visual Studio letöltési lapjára, és telepítse ingyenesen.
Ha telepítenie kell a számítási feladatot, de már rendelkezik Visual Studióval, válassza az Eszközök lekérése>eszközök és szolgáltatások lehetőséget. Elindul a Visual Studio Installer. Válassza a .NET asztali fejlesztés munka terhelését, majd válassza a Módosítás lehetőséget.
Az alkalmazás létrehozásához kövesse az alábbi lépéseket:
Nyissa meg a Visual Studiót. A kezdőablakban válassza az Új projekt létrehozása lehetőséget.
A keresőmezőbe írja be a konzolt , majd a .NET konzolalkalmazás-beállításainak egyikét.
Válassza a Következőlehetőséget.
Adjon meg egy projektnevet, például Console_Parse_JSON, majd válassza a Tovább vagy a Létrehozás lehetőséget.
Válassza ki az ajánlott cél keretrendszert vagy a .NET 8-at, majd válassza a Létrehozáslehetőséget.
Ha nem látja a Console App for .NET projektsablont, lépjen az Eszközök>lekérése eszközök és szolgáltatások lapra, amely megnyitja a Visual Studio Installert. Válassza a .NET asztali fejlesztés munka terhelését, majd válassza a Módosítás lehetőséget.
A Visual Studio létrehozza a konzolprojektet, amely a megoldáskezelőben jelenik meg a jobb oldali panelen.
Ha a projekt elkészült, cserélje le a projekt Program.cs fájljának alapértelmezett kódját a következő mintakódra:
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using System.IO;
namespace Console_Parse_JSON
{
class Program
{
static void Main(string[] args)
{
var localDB = LoadRecords();
string data = GetJsonData();
User[] users = ReadToObject(data);
UpdateRecords(localDB, users);
for (int i = 0; i < users.Length; i++)
{
List<User> result = localDB.FindAll(delegate (User u) {
return u.lastname == users[i].lastname;
});
foreach (var item in result)
{
Console.WriteLine($"Matching Record, got name={item.firstname}, lastname={item.lastname}, age={item.totalpoints}");
}
}
Console.ReadKey();
}
// Deserialize a JSON stream to a User object.
public static User[] ReadToObject(string json)
{
User deserializedUser = new User();
User[] users = { };
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
DataContractJsonSerializer ser = new DataContractJsonSerializer(users.GetType());
users = ser.ReadObject(ms) as User[];
ms.Close();
return users;
}
// Simulated operation that returns JSON data.
public static string GetJsonData()
{
string str = "[{ \"points\":4o,\"firstname\":\"Fred\",\"lastname\":\"Smith\"},{\"lastName\":\"Jackson\"}]";
return str;
}
public static List<User> LoadRecords()
{
var db = new List<User> { };
User user1 = new User();
user1.firstname = "Joe";
user1.lastname = "Smith";
user1.totalpoints = 41;
db.Add(user1);
User user2 = new User();
user2.firstname = "Pete";
user2.lastname = "Peterson";
user2.totalpoints = 30;
db.Add(user2);
return db;
}
public static void UpdateRecords(List<User> db, User[] users)
{
bool existingUser = false;
for (int i = 0; i < users.Length; i++)
{
foreach (var item in db)
{
if (item.lastname == users[i].lastname && item.firstname == users[i].firstname)
{
existingUser = true;
item.totalpoints += users[i].points;
}
}
if (existingUser == false)
{
User user = new User();
user.firstname = users[i].firstname;
user.lastname = users[i].lastname;
user.totalpoints = users[i].points;
db.Add(user);
}
}
}
}
[DataContract]
internal class User
{
[DataMember]
internal string firstname;
[DataMember]
internal string lastname;
[DataMember]
// internal double points;
internal string points;
[DataMember]
internal int totalpoints;
}
}
Keresse meg a piros és a zöld hullámos vonalakat!
Mielőtt megpróbálná elindítani a mintaalkalmazást és futtatni a hibakeresőt, ellenőrizze a kódszerkesztőben a piros és zöld hullámvonalakat. Ezek az IDE kódelemzője által azonosított hibákat és figyelmeztetéseket jelölik. A piros hullámos jelzések fordítási időbeli hibák, amelyeket ki kell javítania a kód futtatása előtt. A zöld hullámos kapcsolók figyelmeztetések. Bár gyakran futtathatja az alkalmazást a figyelmeztetések kijavítása nélkül, ezek a hibák forrása lehetnek, és gyakran időt és problémát takaríthat meg a kivizsgálásukkal. Ezek a figyelmeztetések és hibák a Hibák listája ablakban is megjelennek, ha listanézetet részesíti előnyben.
A mintaalkalmazásban számos piros hullámos kapcsoló látható, amelyeket ki kell javítania, és egy zöldet, amelyet meg kell vizsgálnia. Íme az első hiba.
A hiba kijavításához megtekintheti az IDE egy másik funkcióját, amelyet a villanykörte ikon jelöl.
Nézze meg a villanykörtét!
Az első piros hullámvonal egy fordítási időben jelentkező hibát jelöl. Vigye az egérmutatót fölé, és megjelenik az üzenet The name `Encoding` does not exist in the current context.
Figyelje meg, hogy ez a hiba egy villanykörte ikont jelenít meg a bal alsó részén. A csavarhúzó ikon
mellett a
ikon a gyorsműveleteket jelöli, amelyek segíthetnek a kód beágyazott javításában vagy újrabontásában. A villanykörte olyan problémákat jelöl, amelyeket ki kell javítania. A csavarhúzó olyan problémákra használható, amelyeket esetleg kijavíthat. A hiba megoldásához használja az első javasolt javítást a bal oldali System.Text parancsra kattintva.
Amikor kijelöli ezt az elemet, a Visual Studio hozzáadja az using System.Text utasítást a Program.cs fájl tetejére, és a piros hullámvonal eltűnik. (Ha nem biztos a javasolt javítás által alkalmazott módosításokban, a javítás alkalmazása előtt válassza a jobb oldalon a Módosítások előnézete hivatkozást.)
Az előző hiba egy gyakori hiba, amelyet általában egy új using utasítás kódhoz való hozzáadásával lehet kijavítani. Ehhez számos gyakori, hasonló hiba fordulhat elő, például The type or namespace "Name" cannot be found. az ilyen típusú hibák hiányzó szerelvényhivatkozást jelezhetnek (kattintson a jobb gombbal a projektre, válassza aHivatkozás> lehetőséget), egy hibásan írt nevet vagy egy hiányzó kódtárat, amelyet fel kell vennie (C#esetén kattintson a jobb gombbal a projektre, és válassza a NuGet-csomagok kezelése lehetőséget).
A fennmaradó hibák és figyelmeztetések javítása
Ebben a kódban van néhány további furcsa jel, amit érdemes megnézni. Itt egy gyakori típuskonvertálási hiba jelenik meg. Amikor a hullámos vonal fölé viszi az egérmutatót, láthatja, hogy a kód egy karakterláncot próbál átalakítani egy entière, amely csak akkor támogatott, ha az átalakításhoz explicit kódot ad hozzá.
Mivel a kódelemző nem tudja kitalálni a szándékát, ezúttal nincsenek izzók, amelyek segíthetnek. A hiba elhárításához ismernie kell a kód szándékát. Ebben a példában nem túl nehéz azt látni, hogy points numerikus (egész) értéknek kell lennie, mivel hozzá szeretne adni pointstotalpoints.
A hiba kijavításához módosítsa az pointsUser osztály tagját a következőről:
[DataMember]
internal string points;
ehhez:
[DataMember]
internal int points;
A kódszerkesztő piros hullámos vonalai eltűnnek.
Ezután vigye az egérmutatót a zöld hullámos vonal fölé az points adattag deklarációjában. A kódelemző azt jelzi, hogy a változó soha nem lesz hozzárendelve értékhez.
Ez általában olyan problémát jelent, amelyet ki kell javítani. A mintaalkalmazásban azonban a deszerializálási folyamat során adatokat tárol a points változóban, majd hozzáadja ezt az értéket az totalpoints adattaghoz. Ebben a példában ismeri a kód szándékát, és nyugodtan figyelmen kívül hagyhatja a figyelmeztetést. Ha azonban meg szeretné szüntetni a figyelmeztetést, cserélje le a következő kódot:
item.totalpoints = users[i].points;
a következővel:
item.points = users[i].points;
item.totalpoints += users[i].points;
A zöld squiggle eltűnik.
Kivétel kijavítása
Ha kijavította az összes piros hullámos kapcsolót, és megoldotta – vagy legalábbis kivizsgálta – az összes zöld hullámos kapcsolót, készen áll a hibakereső elindítására és az alkalmazás futtatására.
Nyomja le az
Ekkor a mintaalkalmazás kivételt SerializationException (futtatókörnyezeti hibát) jelez. Vagyis az alkalmazás megfojtja azokat az adatokat, amelyeket szerializálni próbál. Mivel hibakeresési módban indította el az alkalmazást (a hibakereső csatlakoztatva van), a hibakereső kivételsegítője közvetlenül a kivételt eldobó kódot használja, és hasznos hibaüzenetet ad.
A hibaüzenet arra utasítja, hogy az érték 4o nem elemezhető egész számként. Ebben a példában tehát tudja, hogy az adatok hibásak: 4o helyett 40 kellene lennie. Ha azonban nem felügyeli az adatokat egy valós forgatókönyvben (tegyük fel, hogy egy webszolgáltatásból szerzi be), mit tesz vele? Hogyan lehet ezt kijavítani?
Ha kivételt ér el, fel kell tennie (és megválaszolnia) néhány kérdést:
Ez a kivétel csak egy hiba, amelyet kijavíthat? Vagy
Ez a kivétel olyasmi, amit a felhasználók tapasztalhatnak?
Ha az előbbiről van szó, javítsa ki a hibát. (A mintaalkalmazásban ki kell javítania a hibás adatokat.) Ha ez utóbbi következik be, előfordulhat, hogy a kódban egy try/catch blokk használatával kell kezelnie a kivételt (a következő szakaszban további lehetséges stratégiákat tekintünk meg). A mintaalkalmazásban cserélje le a következő kódot:
users = ser.ReadObject(ms) as User[];
a következő kóddal:
try
{
users = ser.ReadObject(ms) as User[];
}
catch (SerializationException)
{
Console.WriteLine("Give user some info or instructions, if necessary");
// Take appropriate action for your app
}
A try/catch blokkok némi teljesítményköltséggel rendelkeznek, ezért csak akkor érdemes használni őket, ha valóban szüksége van rájuk, azaz hol (a) fordulhatnak elő az alkalmazás kiadási verziójában, és ahol (b) a módszer dokumentációja azt jelzi, hogy ellenőriznie kell a kivételt (feltéve, hogy a dokumentáció elkészült!). Sok esetben megfelelően kezelheti a kivételeket, és a felhasználónak soha nem kell tudnia róla.
Íme néhány fontos tipp a kivételkezeléshez:
Ne használjon üres fogási blokkot, például
catch (Exception) {}, amely nem tesz megfelelő műveletet a hibák felfedéséhez vagy kezeléséhez. Az üres vagy neminformatív fogási blokkok elrejthetik a kivételeket, és nehezebbé tehetik a kód hibakeresését ahelyett, hogy megkönnyítenék.Használja a kivételt
try/catchokozó adott függvény körüli blokkot (ReadObjecta mintaalkalmazásban). Ha nagyobb kódtömb körül használja, a hiba helyét elrejti. Például ne használja aztry/catchitt látható szülőfüggvényReadToObjecthívása körüli blokkot, vagy nem fogja tudni, hogy pontosan hol történt a kivétel.// Don't do this try { User[] users = ReadToObject(data); } catch (SerializationException) { }Az alkalmazásban nem ismert függvények, különösen a külső adatokkal (például webes kérésekkel) kommunikáló függvények esetében tekintse meg a dokumentációban, hogy milyen kivételeket fog eredményezni a függvény. Ezek kritikus fontosságú információk lehetnek a megfelelő hibakezeléshez és az alkalmazás hibakereséséhez.
A mintaalkalmazás esetében javítsa ki a SerializationException elemet a GetJsonData metódusban, a 4o-t 40-ra módosítva.
Jótanács
Ha rendelkezik Copilot, a kivételek hibakeresése során kaphat mesterséges intelligencia által nyújtott segítséget. Csak keresse meg a Ask Copilot
gomb. További információért lásd: Hibakeresés a Copilot segítségével.
Tisztázd a kódod szándékát az assert állítás használatával
Válassza az
a hibakeresési eszköztáron (Ctrl + Shift + F5). Ez kevesebb lépésben újraindítja az alkalmazást. A következő kimenet jelenik meg a konzolablakban.
A kimenetben látható, hogy valami nem megfelelő. A harmadik rekord neve és vezetékneve üresen maradt!
Itt az ideje, hogy beszéljünk egy hasznos, gyakran alulértékelt kódolási gyakorlatról, amely a assert utasítások használata a függvényekben. Az alábbi kód hozzáadásával egy futásidejű ellenőrzést szúrhat be, hogy biztosítsa firstname és lastname nem null. Cserélje le a következő kódot a UpdateRecords metódusban:
if (existingUser == false)
{
User user = new User();
user.firstname = users[i].firstname;
user.lastname = users[i].lastname;
a következővel:
// Also, add a using statement for System.Diagnostics at the start of the file.
Debug.Assert(users[i].firstname != null);
Debug.Assert(users[i].lastname != null);
if (existingUser == false)
{
User user = new User();
user.firstname = users[i].firstname;
user.lastname = users[i].lastname;
Ha a fejlesztési folyamat során ilyen utasításokat ad assert hozzá a függvényekhez, segíthet meghatározni a kód szándékát. Az előző példában a következő elemeket adhatja meg:
- Az utónévhez érvényes sztring szükséges
- A vezetéknévhez érvényes karakterlánc szükséges
A szándék ilyen módon történő megadásával érvényesíti a követelményeket. Ez egy egyszerű és praktikus módszer, amellyel a fejlesztés során feltárhatja a hibákat. (assert utasítások is használatosak az egységtesztek fő elemeként.)
Válassza az
a hibakeresési eszköztáron (Ctrl + Shift + F5).
Megjegyzés:
A assert kód csak hibakeresési buildben aktív.
Újraindításkor a hibakereső a assert utasításon szünetel, mert a kifejezés értéke users[i].firstname != null, ahelyett hogy false lenne.
A assert hiba azt jelzi, hogy van egy probléma, amelyet ki kell vizsgálnia.
assert számos olyan forgatókönyvet lefedhet, ahol nem feltétlenül lát kivételt. Ebben a példában a felhasználó nem lát kivételt, és a rendszer egy null értéket ad hozzá a rekordok listájához firstname formájában. Ez a feltétel később problémákat okozhat (például megjelenik a konzol kimenetében), és nehezebb lehet a hibakeresés.
Megjegyzés:
Olyan helyzetekben, amikor egy metódust hív meg az null értéken, NullReferenceException az eredmény. Általában kerülni szeretné, hogy try/catch blokkot használjon egy általános kivételhez, ami nem kötődik konkrét könyvtárfüggvényhez. Bármely objektum dobhat egy NullReferenceException. Ha nem biztos benne, ellenőrizze a könyvtárfüggvény dokumentációját.
A hibakeresési folyamat során érdemes megtartani egy adott assert utasítást mindaddig, amíg meg nem győződik róla, hogy szükséges egy konkrét kódjavításra cserélni. Tegyük fel, hogy úgy dönt, hogy a felhasználó kivételt tapasztalhat az alkalmazás kiadási buildjében. Ebben az esetben újra kell képeznie a kódot annak érdekében, hogy az alkalmazás ne okoz-e végzetes kivételt, vagy más hibát eredményez. A kód kijavításához cserélje le a következő kódot:
if (existingUser == false)
{
User user = new User();
a következő kóddal:
if (existingUser == false && users[i].firstname != null && users[i].lastname != null)
{
User user = new User();
A kód követelményeinek teljesítése érdekében használja ezt a kódot, és ügyeljen arra, hogy az adatokhoz ne adjon hozzá olyan rekordot, amelynek firstname vagy lastname értéke null.
Ebben a példában hozzáadtuk a két assert utasítást egy cikluson belül. Általában, amikor a assert használata során, érdemes a assert utasításokat a függvény vagy metódus belépési pontján (elején) hozzáadni. Jelenleg a UpdateRecords metódust nézed meg a mintaalkalmazásban. Ebben a metódusban tudja, hogy bajban van, ha valamelyik metódusargumentum az null, ezért ellenőrizze mindkettőt egy assert utasítással a függvény belépési pontján.
public static void UpdateRecords(List<User> db, User[] users)
{
Debug.Assert(db != null);
Debug.Assert(users != null);
Az előző utasítások esetében a szándék az, hogy a meglévő adatokat (db) betöltse, és új adatokat (users) kérjen le a frissítés előtt.
Bármilyen olyan kifejezéssel használható a assert, amely true-re vagy false-re oldódik fel. Például így adhat hozzá egy assert utasítást.
Debug.Assert(users[0].points > 0);
Az előző kód akkor hasznos, ha a következő szándékot szeretné megadni: a felhasználó rekordjának frissítéséhez nullánál (0) nagyobb új pontértékre van szükség.
A kód vizsgálata a hibakeresőben
Ok, most, hogy kijavított mindent, ami a mintaalkalmazással kapcsolatos kritikus fontosságú, továbbléphet más fontos dolgokra!
Bemutattuk a hibakereső kivételsegítőjét, de a hibakereső sokkal hatékonyabb eszköz, amellyel más műveleteket is elvégezhet, például végiglépkedhet a kódon, és megvizsgálhatja annak változóit. Ezek a hatékonyabb képességek számos forgatókönyvben hasznosak, különösen a következő forgatókönyvekben:
Megpróbál elkülöníteni egy futtatókörnyezeti hibát a kódban, de nem tudja elvégezni a korábban tárgyalt módszerek és eszközök használatával.
Ellenőrizni szeretné a kódot, azaz figyelnie kell a futtatás közben, hogy biztosan a várt módon viselkedjen, és azt tegye, amit szeretne.
Tanulságos megfigyelni a kódot futás közben. Így többet is megtudhat a kódról, és gyakran azonosíthatja a hibákat, mielőtt nyilvánvaló tüneteket észlelnének.
Ha szeretné megtudni, hogyan használhatja a hibakereső alapvető funkcióit, tekintse meg az abszolút kezdők hibakeresését.
Teljesítményproblémák elhárítása
Más típusú hibák közé tartozik a nem hatékony kód, amely miatt az alkalmazás lassan fut, vagy túl sok memóriát használ. A teljesítmény optimalizálása általában az alkalmazásfejlesztés későbbi részében történik. Előfordulhat azonban, hogy korán teljesítményproblémákba ütközik (például azt látja, hogy az alkalmazás egy része lassan fut), és előfordulhat, hogy korábban tesztelnie kell az alkalmazást a profilkészítési eszközökkel. További információ a profilkészítési eszközökről, például a PROCESSZORhasználati eszközről és a Memóriaelemzőről: Először tekintse meg a profilkészítési eszközöket.
Kapcsolódó tartalom
Ebben a cikkben megtanulhatta, hogyan kerülheti el és javíthatja ki a kód számos gyakori hibáját, és hogy mikor érdemes használni a hibakeresőt. A következő lépésben többet is megtudhat a Visual Studio hibakeresőjének használatáról a hibák kijavításához.