Daha iyi kod yazmanıza yardımcı olacak hata ayıklama teknikleri ve araçları

Kodunuzdaki hataları ve hataları düzeltmek zaman alan ve bazen sinir bozucu bir görev olabilir. Etkili bir şekilde hata ayıklamayı öğrenmek zaman alır. Visual Studio gibi güçlü bir IDE işinizi çok daha kolay hale getirebilir. IDE, hataları düzeltmenize ve kodunuzun hatalarını daha hızlı ayıklamanıza ve daha az hatayla daha iyi kod yazmanıza yardımcı olabilir. Bu makalede "hata düzeltme" işleminin bütünsel bir görünümü sağlanır; böylece kod çözümleyicisini ne zaman kullanacağınızı, hata ayıklayıcıyı ne zaman kullanacağınızı, özel durumları nasıl düzeltebileceğinizi ve amaç için nasıl kod oluşturabileceğinizi öğrenebilirsiniz. Hata ayıklayıcısını kullanmanız gerektiğini zaten biliyorsanız bkz . İlk olarak hata ayıklayıcıya bakın.

Bu makalede, kodlama oturumlarınızı daha üretken hale getirmek için IDE ile çalışmayı öğreneceksiniz. Aşağıdakiler gibi çeşitli görevlere değiniyoruz:

  • IDE'nin kod çözümleyicisini kullanarak kodunuzu hata ayıklamaya hazırlama

  • Özel durumları düzeltme (çalışma zamanı hataları)

  • Amaç için kodlama yaparak hataları en aza indirme (onay kullanarak)

  • Hata ayıklayıcı ne zaman kullanılır?

Bu görevleri göstermek için, uygulamalarınızda hata ayıklamaya çalışırken karşılaşabileceğiniz en yaygın hata ve hata türlerinden birkaçını gösteririz. Örnek kod C# olsa da kavramsal bilgiler genellikle C++, Visual Basic, JavaScript ve Visual Studio tarafından desteklenen diğer diller (not edilenler dışında) için geçerlidir. Ekran görüntüleri C# dilindedir.

Bazı hatalar ve hatalar içeren örnek bir uygulama oluşturma

Aşağıdaki kodda Visual Studio IDE kullanarak düzeltebileceğiniz bazı hatalar vardır. Bu uygulama, bir işlemden JSON verilerini alma, verileri bir nesneye seri durumdan çıkarma ve basit bir listeyi yeni verilerle güncelleştirme simülasyonu sağlayan basit bir uygulamadır.

Uygulamayı oluşturmak için Visual Studio'yu ve .NET masaüstü geliştirme iş yükünü yüklemiş olmanız gerekir.

  • Visual Studio'yu henüz yüklemediyseniz Visual Studio indirmeleri sayfasına giderek ücretsiz yükleyin.

  • İş yükünü yüklemeniz gerekiyorsa ancak Visual Studio'ya zaten sahipseniz Araçlar Araçları>ve Özellikleri Al'ı seçin. Visual Studio Yükleyicisi başlatılır. .NET masaüstü geliştirme iş yükünü ve ardından Değiştir'i seçin.

Uygulamayı oluşturmak için şu adımları izleyin:

  1. Visual Studio'yu açın. Başlangıç penceresinde Yeni proje oluştur'u seçin.

  2. Arama kutusuna konsol yazın ve ardından .NET için Konsol Uygulaması seçeneklerinden birini girin.

  3. İleri'yi seçin.

  4. Console_Parse_JSON gibi bir proje adı girin ve ardından uygun olduğunda İleri veya Oluştur'u seçin.

    Önerilen hedef çerçeveyi veya .NET 8'i ve ardından Oluştur'u seçin.

    .NET için Konsol Uygulaması proje şablonunu görmüyorsanız Araçlar Araçları>ve Özellikleri Al'a gidin ve Visual Studio Yükleyicisi açılır. .NET masaüstü geliştirme iş yükünü ve ardından Değiştir'i seçin.

    Visual Studio, sağ bölmedeki Çözüm Gezgini görüntülenen konsol projesini oluşturur.

Proje hazır olduğunda, projenin Program.cs dosyasındaki varsayılan kodu aşağıdaki örnek kodla değiştirin:

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;
    }
}

Kırmızı ve yeşil dalgalı çizgiler bulun!

Örnek uygulamayı başlatmayı ve hata ayıklayıcıyı çalıştırmayı denemeden önce kod düzenleyicisinde kırmızı ve yeşil dalgalı çizgiler olup olmadığını denetleyin. Bunlar, IDE'nin kod çözümleyicisi tarafından tanımlanan hataları ve uyarıları temsil eder. Kırmızı dalgalı çizgiler derleme zamanı hatalarıdır ve kodu çalıştırmadan önce düzeltmeniz gerekir. Yeşil dalgalı çizgiler uyarıdır. Genellikle uyarıları düzeltmeden uygulamanızı çalıştırabilirsiniz, ancak bunlar bir hata kaynağı olabilir ve genellikle bunları araştırarak kendinize zaman ve sorun tasarrufu sağlarsınız. Liste görünümünü tercih ediyorsanız, bu uyarılar ve hatalar Hata Listesi penceresinde de gösterilir.

Örnek uygulamada, düzeltmeniz gereken birkaç kırmızı dalgalı çizgi ve araştırmanız gereken yeşil bir dalgalı çizgi görürsünüz. İlk hata şu şekildedir.

Kırmızı dalgalı çizgi olarak gösterilen hata

Bu hatayı düzeltmek için IDE'nin ampul simgesiyle temsil edilen başka bir özelliğine bakabilirsiniz.

Ampulü kontrol edin!

İlk kırmızı dalgalı çizgi derleme zamanı hatasını temsil eder. Üzerine geldiğinizde iletisini The name `Encoding` does not exist in the current contextgörürsünüz.

Bu hatanın sol altta bir ampul simgesi gösterdiğine dikkat edin. Tornavida simgesiyle birlikte ampul simgesitornavida simgesiampul simgesi, satır içi kodu düzeltmenize veya yeniden düzenlemenize yardımcı olabilecek Hızlı İşlemler'i temsil eder. Ampul, düzeltmeniz gereken sorunları temsil eder. Tornavida, düzeltmeyi seçebileceğiniz sorunlara yöneliktir. Soldaki System.Text'i kullanarak bu hatayı düzeltmek için önerilen ilk düzeltmeyi kullanın.

Kodu düzeltmek için ampulü kullanma

Bu öğeyi seçtiğinizde Visual Studio, Program.cs dosyasının en üstüne deyimini ekler using System.Text ve kırmızı dalgalı çizgi kaybolur. (Önerilen bir düzeltme tarafından uygulanan değişikliklerden emin değilsenizDüzeltmeyi uygulamadan önce sağdaki değişiklikleri önizleme bağlantısı.)

Yukarıdaki hata, genellikle kodunuz için yeni using bir deyim ekleyerek düzeltdiğiniz yaygın bir hatadır. Bu tür hatalar eksik bir derleme başvurusunu gösterebilir (projeye sağ tıklayın, Başvuru Ekle'yi>seçin), yanlış yazılmış bir ad veya eklemeniz gereken eksik bir kitaplık (C# için projeye sağ tıklayın ve NuGet Paketlerini Yönet'i seçin) gibi The type or namespace "Name" cannot be found. yaygın ve benzer hatalar vardır.

Kalan hataları ve uyarıları düzeltme

Bu kodda bakmak için birkaç dalgalı çizgi daha vardır. Burada yaygın bir tür dönüştürme hatası görürsünüz. Dalgalı çizginin üzerine geldiğinizde, kodun bir dizeyi int'e dönüştürmeye çalıştığını görürsünüz; bu, dönüştürmeyi yapmak için açık kod eklemediğiniz sürece desteklenmez.

Tür dönüştürme hatası

Kod çözümleyicisi amacınızı tahmin etmediğinden, bu kez size yardımcı olacak ampuller yoktur. Bu hatayı düzeltmek için kodun amacını bilmeniz gerekir. Bu örnekte, öğesine eklemeye pointstotalpointsçalıştığınız için bunun bir sayısal (tamsayı) değeri olması gerektiğini görmek points çok zor değildir.

Bu hatayı düzeltmek için sınıfın üyesini pointsUser şu şekilde değiştirin:

[DataMember]
internal string points;

şu şekilde:

[DataMember]
internal int points;

Kod düzenleyicisindeki kırmızı dalgalı çizgiler kaybolur.

Ardından, veri üyesinin bildiriminde yeşil dalgalı çizginin points üzerine gelin. Kod çözümleyicisi, değişkenin hiçbir zaman bir değer atanmadığından size bildirir.

Atanmamış değişken için uyarı iletisi

Bu genellikle düzeltilmesi gereken bir sorunu temsil eder. Ancak örnek uygulamada, seri durumdan çıkarma işlemi sırasında verileri değişkende points depoluyor ve ardından bu değeri veri üyesine totalpoints eklisiniz. Bu örnekte, kodun amacını biliyorsunuz ve uyarıyı güvenle yoksayabilirsiniz. Ancak, uyarıyı ortadan kaldırmak istiyorsanız aşağıdaki kodu değiştirebilirsiniz:

item.totalpoints = users[i].points;

şununla değiştirin:

item.points = users[i].points;
item.totalpoints += users[i].points;

Yeşil dalgalı çizgi yok oluyor.

Özel durumu düzeltme

Tüm kırmızı dalgalı çizgiler düzeltildiğinde veya en azından araştırıldığında tüm yeşil dalgalı çizgiler düzeltildiğinde, hata ayıklayıcıyı başlatmaya ve uygulamayı çalıştırmaya hazır olursunuz.

Hata Ayıklama araç çubuğunda F5 (Hata AyıklamaYı > Başlat Hata Ayıklama) veya Hata Ayıklamayı Başlat düğmesine Hata Ayıklamayı Başlat basın.

Bu noktada, örnek uygulama bir SerializationException özel durum (çalışma zamanı hatası) oluşturur. Başka bir ifadeyle uygulama, serileştirmeye çalıştığı verilerde boğulur. Uygulamayı hata ayıklama modunda başlattığınız için (hata ayıklayıcısı eklendi), hata ayıklayıcısının Özel Durum Yardımcısı sizi doğrudan özel durum oluşturan koda götürür ve size yararlı bir hata iletisi verir.

SerializationException oluşuyor

Hata iletisi, değerin 4o tamsayı olarak ayrıştırılamını bildirir. Bu örnekte verilerin kötü olduğunu biliyorsunuz: 4o olmalıdır 40. Öte yandan, gerçek bir senaryoda verilerin denetimi siz değilseniz (örneğin, bir web hizmetinden alıyorsanız), bu konuda ne yaparsınız? Bunu nasıl düzeltirsiniz?

Bir özel duruma bastığınızda birkaç soru sormanız (ve yanıtlamanız) gerekir:

  • Bu özel durum yalnızca düzeltebileceğiniz bir hata mı? Veya

  • Bu özel durum, kullanıcılarınızın karşılaşabileceği bir durum mudur?

Sorun eskiyse hatayı düzeltin. (Örnek uygulamada hatalı verileri düzeltmeniz gerekir.) Bu ikinciyse, bir blok kullanarak try/catch kodunuzda özel durumu işlemeniz gerekebilir (sonraki bölümde diğer olası stratejilere göz atacağız). Örnek uygulamada aşağıdaki kodu değiştirin:

users = ser.ReadObject(ms) as User[];

yerine şu kodu yazın:

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
}

Bir try/catch bloğun performans maliyeti vardır, bu nedenle bunları yalnızca gerçekten ihtiyacınız olduğunda, yani (a) uygulamanın sürüm sürümünde ortaya çıkabilirken ve (b) yöntemin belgeleri özel durumu denetlemeniz gerektiğini gösterir (belgelerin tamamlandığı varsayılarak!). Çoğu durumda, bir özel durumu uygun şekilde işleyebilirsiniz ve kullanıcının bunu bilmesine asla gerek kalmaz.

Özel durum işlemeye yönelik birkaç önemli ipucu aşağıdadır:

  • Bir hatayı ortaya çıkarmak veya işlemek için uygun eylemi gerçekleştirmeyen gibi catch (Exception) {}boş bir catch bloğu kullanmaktan kaçının. Boş veya hiç biçimlendirilmemiş bir catch bloğu özel durumları gizleyebilir ve kodunuzun hatalarını ayıklamayı kolaylaştırmak yerine daha zor hale getirebilir.

  • try/catch Özel durumReadObject oluşturan (örnek uygulamada) belirli bir işlevin etrafındaki bloğu kullanın. Bunu daha büyük bir kod öbekleri etrafında kullanırsanız hatanın konumunu gizlemiş olursunuz. Örneğin, burada gösterilen üst işlevine ReadToObjectyapılan çağrının etrafındaki bloğu kullanmayıntry/catch; aksi durumda özel durumun tam olarak nerede oluştuğunu bilemezsinsiniz.

    // Don't do this
    try
    {
        User[] users = ReadToObject(data);
    }
    catch (SerializationException)
    {
    }
    
  • Özellikle dış verilerle (web isteği gibi) etkileşim kuran işlevler olmak üzere uygulamanıza eklediğiniz tanıdık olmayan işlevler için, işlevin oluşturma olasılığı olan özel durumları görmek için belgelere bakın. Bu, doğru hata işleme ve uygulamanızda hata ayıklama için kritik bilgiler olabilir.

Örnek uygulama için yöntemini olarak değiştirerek yöntemini düzeltin SerializationExceptionGetJsonData40.4o

İpucu

Copilot kullanıyorsanız özel durumlarda hata ayıklarken yapay zeka yardımı alabilirsiniz. Copilot'a Copilot'a Sor düğmesinin ekran görüntüsü. Sor düğmesini arayın. Daha fazla bilgi için bkz . Copilot ile hata ayıklama.

Assert kullanarak kod amacınızı netleştirin

Hata Ayıklama Araç Çubuğu'nda Yeniden BaşlatUygulamayı Yeniden Başlat düğmesini seçin (Ctrl + Shift + F5). Bu işlem, uygulamayı daha az adımda yeniden başlatır. Konsol penceresinde aşağıdaki çıkışı görürsünüz.

Çıktıdaki null değer

Bu çıkışta doğru olmayan bir şey görebilirsiniz. Üçüncü kaydın ad ve soyadı değerleri boş!

Bu, işlevlerinizde deyimleri kullanmak assert için genellikle az kullanılan yararlı bir kodlama uygulaması hakkında konuşmak için iyi bir zamandır. Aşağıdaki kodu ekleyerek, ve olmadığından nullemin olmak firstnamelastname için bir çalışma zamanı denetimi eklersiniz. yönteminde UpdateRecords aşağıdaki kodu değiştirin:

if (existingUser == false)
{
    User user = new User();
    user.firstname = users[i].firstname;
    user.lastname = users[i].lastname;

şununla değiştirin:

// 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;

Geliştirme işlemi sırasında işlevlerinize bunun gibi deyimler ekleyerek assert kodunuzun amacını belirtmenize yardımcı olabilirsiniz. Yukarıdaki örnekte aşağıdaki öğeleri belirteceğiz:

  • Ad için geçerli bir dize gereklidir
  • Soyadı için geçerli bir dize gerekiyor

Amacı bu şekilde belirterek gereksinimlerinizi zorunlu hale getirebilirsiniz. Bu, geliştirme sırasında hataları ortaya çıkarabilmek için kullanabileceğiniz basit ve kullanışlı bir yöntemdir. (assert deyimleri, birim testlerinde ana öğe olarak da kullanılır.)

Hata Ayıklama Araç Çubuğu'nda Yeniden BaşlatUygulamayı Yeniden Başlat düğmesini seçin (Ctrl + Shift + F5).

Not

Kod assert yalnızca Hata Ayıklama derlemesinde etkindir.

Yeniden başlattığınızda, ifade users[i].firstname != null yerine olarak değerlendirildiğinden false hata ayıklayıcı deyiminde trueduraklatılırassert.

Assert, false olarak çözümler

Hata assert , araştırmanız gereken bir sorun olduğunu bildirir. assert bir özel durum görmeniz gerekmeyecek birçok senaryoya değinebilir. Bu örnekte kullanıcı özel durum görmez ve kayıt listenizde olduğu gibi firstname bir null değer eklenir. Bu koşul daha sonra sorunlara neden olabilir (konsol çıkışında gördüğünüz gibi) ve hata ayıklaması daha zor olabilir.

Not

Değeri üzerinde null bir yöntem çağırdığınız senaryolarda, bir NullReferenceException sonuç. Normalde, belirli bir try/catch kitaplık işlevine bağlı olmayan bir özel durum olan genel bir özel durum için blok kullanmaktan kaçınmak istersiniz. Herhangi bir nesne bir NullReferenceExceptionoluşturabilir. Emin değilseniz kitaplık işlevinin belgelerine bakın.

Hata ayıklama işlemi sırasında, belirli assert bir deyimi gerçek bir kod düzeltmesiyle değiştirmeniz gerektiğini anlayana kadar tutmak iyi olur. Kullanıcının uygulamanın bir yayın derlemesinde özel durumla karşılaşabileceğine karar verelim. Bu durumda, uygulamanızın önemli bir özel durum oluşturmadığından veya başka bir hataya neden olmadığından emin olmak için kodu yeniden düzenlemeniz gerekir. Bu nedenle, bu kodu düzeltmek için aşağıdaki kodu değiştirin:

if (existingUser == false)
{
    User user = new User();

yerine şu kodu yazın:

if (existingUser == false && users[i].firstname != null && users[i].lastname != null)
{
    User user = new User();

Bu kodu kullanarak kod gereksinimlerinizi karşılar ve veya lastname değerine sahip firstname bir kaydın null verilere eklenmediğinden emin olursunuz.

Bu örnekte, döngünün içine iki assert deyimini ekledik. Genellikle kullanırken, assertbir işlevin veya yöntemin giriş noktasına (başlangıç) deyimleri eklemek assert en iyisidir. Şu anda örnek uygulamadaki yöntemine bakıyorsunuz UpdateRecords . Bu yöntemde, yöntem bağımsız değişkenlerinden biri ise sorun yaşıyorsunuz demektir null, bu nedenle her ikisini de işlevin giriş noktasındaki bir assert deyimle denetleyin.

public static void UpdateRecords(List<User> db, User[] users)
{
    Debug.Assert(db != null);
    Debug.Assert(users != null);

Önceki deyimler için amacınız, herhangi bir şeyi güncelleştirmeden önce var olan verileri (db) yükleyip yeni verileri (users) almanızdır.

veya falseiçin çözümleyen true herhangi bir ifade türüyle kullanabilirsinizassert. Örneğin, bunun gibi bir assert deyim ekleyebilirsiniz.

Debug.Assert(users[0].points > 0);

Yukarıdaki kod, şu amacı belirtmek istiyorsanız kullanışlıdır: Kullanıcının kaydını güncelleştirmek için sıfırdan (0) büyük yeni bir nokta değeri gereklidir.

Hata ayıklayıcıda kodunuzu inceleme

Tamam, artık örnek uygulamada yanlış olan kritik her şeyi düzeltebildiğinize göre, diğer önemli konulara geçebilirsiniz!

Size hata ayıklayıcının Özel Durum Yardımcısı'nı gösterdik, ancak hata ayıklayıcısı, kodunuzu adım adım ilerletip değişkenlerini incelemeniz gibi başka işlemler yapmanıza da olanak tanıyan çok daha güçlü bir araçtır. Bu daha güçlü özellikler, özellikle aşağıdaki senaryolar olmak üzere birçok senaryoda kullanışlıdır:

  • Kodunuzda bir çalışma zamanı hatasını yalıtmaya çalışıyorsunuz, ancak daha önce açıklanan yöntemleri ve araçları kullanarak bunu yapamıyorsunuz.

  • Kodunuzu doğrulamak, yani beklediğiniz şekilde çalıştığından ve istediğiniz şekilde çalıştığından emin olmak için çalışırken izlemek istiyorsunuz.

    Çalışırken kodunuzu izlemeniz öğreticidir. Kodunuz hakkında bu şekilde daha fazla bilgi edinebilir ve hataları genellikle belirgin belirtileri göstermeden önce tanımlayabilirsiniz.

Hata ayıklayıcının temel özelliklerini kullanmayı öğrenmek için bkz . Yeni başlayanlar için hata ayıklama.

Performans sorunlarını çözme

Başka türdeki hatalar, uygulamanızın yavaş çalışmasına veya çok fazla bellek kullanmasına neden olan verimsiz kod içerir. Genellikle performansı iyileştirmek, uygulama geliştirme aşamasında daha sonra yapabileceğiniz bir işlemdir. Ancak, performans sorunlarıyla erken karşılaşabilirsiniz (örneğin, uygulamanızın bir bölümünün yavaş çalıştığını görürsünüz) ve uygulamanızı erken profil oluşturma araçlarıyla test etmeniz gerekebilir. CPU Kullanımı aracı ve Bellek Çözümleyicisi gibi profil oluşturma araçları hakkında daha fazla bilgi için bkz . Profil oluşturma araçlarına ilk bakış.

Bu makalede, kodunuzdaki birçok yaygın hatayı önlemeyi ve düzeltmeyi ve hata ayıklayıcıyı ne zaman kullanacağınızı öğrendiniz. Ardından, hataları düzeltmek için Visual Studio hata ayıklayıcısını kullanma hakkında daha fazla bilgi edinin.