Skip to main content

Debugging and Diagnostics

Level: Intermediate

ℹ️ What You'll Learn
  • Breakpoint types and conditions
  • Watch windows and variable inspection
  • Exception handling and debugging
  • Debug console and immediate window
  • Performance profiling
  • Diagnostic tools

Breakpoint Types

Simple Breakpoint

Click left margin → F9 to toggle:

public class StudentService
{
public Student GetStudent(int id)
{
// Breakpoint here - execution stops
var student = _repository.GetStudent(id);
return student;
}
}

Red dot = breakpoint active.

Conditional Breakpoint

Right-click breakpoint → Filter...:

Filter: id == 101
Hit Count: 1

Stop only when condition true.

Tracepoint

Right-click breakpoint → Actions... → "Print a message":

Breakpoint message: Student retrieved: {student.Name}

Logs to output without stopping.

Watch Window

Debug → Windows → Watch:

var student = new Student
{
RollNumber = "SMS-2024-001",
Name = "Ravi Kumar",
ClassName = "10-A",
Status = "Active"
};

// In Watch window, add:
// student.RollNumber
// student.ClassName
// student.Status == "Active" ? "OK" : "INACTIVE"

Watch expressions evaluate during execution.

Locals Window

Debug → Windows → Locals — auto-shows all local variables:

public void ProcessFeePayment(int studentId, decimal amount)
{
// Locals shows:
// studentId = 101
// amount = 5000
var payment = new FeePayment { Amount = amount };
// After this line, Locals shows:
// payment = { Amount: 5000, PaidOn: null }
}

Updates automatically at each step.

Immediate Window

Debug → Windows → Immediate (execute code during debug):

// While paused, type in Immediate window:
? student.Name
// Output: "Ravi Kumar"

? student.Status == "Active"
// Output: true

student.ClassName = "10-B"
// Modify variable during debug

Execute statements without stopping execution.

Exception Handling Debugging

Break on exceptions:

Debug → Windows → Exception Settings:

☑ Common Language Runtime Exceptions
☑ Advanced debugging features

Stop when exception thrown:

public Student GetStudent(int id)
{
try
{
if (id <= 0)
throw new ArgumentException("Invalid student ID");

return _repository.GetStudent(id);
}
catch (Exception ex)
{
// Debug breaks here on exception
// Inspect ex.Message, ex.StackTrace
throw;
}
}

Call Stack Window

Debug → Windows → Call Stack — shows execution path:

> GetStudent(int id) - StudentService.cs:25
> GetStudentList() - StudentController.cs:12
> Main(string[] args) - Program.cs:5

Click frame to jump to that code location.

Threads Window

Debug → Windows → Threads — monitor parallel execution:

For SMS background processing:

// Thread 1: Main UI thread processing student list
// Thread 2: Background thread calculating fees
// Thread 3: Async email notifications

// Threads window shows all active threads
// Set which thread to debug

Performance Profiler

Debug → Performance Profiler:

  1. Select "CPU Usage"
  2. Start recording
  3. Navigate through SMS (student list, create exam, etc)
  4. Stop recording
  5. Analyze hot spots:
StudentService.GetStudents() - 45% CPU
ExamService.CalculateResults() - 30% CPU
FeeCalculation() - 15% CPU

Identify bottlenecks.

Memory Diagnostic Tools

Debug → Performance Profiler → Memory Usage:

  1. Snapshot heap
  2. Perform actions (add 1000 students, download reports)
  3. Snapshot again
  4. Compare:
Before: 50 MB
After: 250 MB
Growth: 200 MB (mostly Student objects)

Find memory leaks.

SMS Debugging Scenario

Debug student fee calculation:

public decimal CalculateTotalFees(int studentId)
{
var student = _studentService.GetStudent(studentId); // Breakpoint 1
var classRate = GetClassFeeRate(student.ClassName); // Breakpoint 2
var discount = GetDiscount(student.Status); // Breakpoint 3

decimal totalFees = 0;
if (student.Status == "Active")
{
totalFees = classRate - discount; // Breakpoint 4 - watch (totalFees)
}

return totalFees; // Expected: 50000
}

Step through, inspect variables at each stage.

Debug Output Window

Debug → Windows → Output:

Logs from Debug.WriteLine():

public void CreateStudent(Student student)
{
Debug.WriteLine($"Creating student: {student.Name}");
Debug.WriteLine($"Class: {student.ClassName}");

_repository.Add(student);

Debug.WriteLine($"Student {student.Id} created successfully");
}

// Output window shows:
// Creating student: Priya Sharma
// Class: 10-B
// Student 102 created successfully

Key Shortcuts

ShortcutAction
F5Start debugging
F9Toggle breakpoint
F10Step over
F11Step into
Shift + F11Step out
Ctrl + Alt + WOpen Watch window
Ctrl + Alt + LOpen Locals window
Ctrl + Alt + IOpen Immediate window
Ctrl + Alt + COpen Call Stack

Key Takeaways

  • Breakpoints = pause execution to inspect state
  • Watch window = monitor variables over time
  • Exceptions = catch and understand errors
  • Call stack = understand execution flow
  • Performance profiler = find bottlenecks
  • Memory diagnostics = find leaks
💡 Debugging Pro Tip

Use tracepoints instead of Console.WriteLine() — no code changes, automatic logging during debug.

⚠️ Common Debugging Mistakes
  1. Not clearing breakpoints — Old breakpoints remain, slow debugging
  2. Watching too many variables — Performance impact
  3. Forgetting to stop debugging — Resource leak
  4. Not checking Exception Settings — Miss important exceptions
🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Visual Studio Debugging. Try these prompts:

  • "How do I set a conditional breakpoint?"
  • "What's the difference between Step Over and Step Into?"
  • "How do I find memory leaks?"
  • "Quiz me on debugging"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

nexcoding.in