System.Diagnostics.Debug
.NET標準のデバッグ出力クラス。DEBUG条件付きコンパイルにより本番ビルドでは自動的に無効化。Visual Studio等のIDEでのデバッグセッションに特化し、開発時のトレース情報出力に使用される軽量なデバッグツール。
ライブラリ
System.Diagnostics.Debug
概要
System.Diagnostics.Debugは「.NET Framework/.NET Core向けの組み込みデバッグ・診断ライブラリ」として提供される、Microsoftの標準ロギングソリューションです。.NET Frameworkに最初から含まれているため、外部依存関係なしで利用可能。主にデバッグビルド時の開発支援とトラブルシューティングを目的とし、コンパイル時条件付きコンパイルによりリリースビルドでは自動的に除去される設計。Visual Studioとの密接な統合により、ブレークポイント、ステップ実行、変数ウォッチとシームレスに連携し、.NET開発者にとって最も身近なデバッグツールとして位置づけられています。
詳細
System.Diagnostics.Debug 2025年版は、.NET 8以降の最新ランタイムと完全統合され、高度なパフォーマンス診断とメモリ分析機能を提供しています。従来のDebug.WriteLine()からStructured Loggingサポートまで幅広い出力オプションを提供し、クラウドネイティブアプリケーションでの分散トレーシングとも連携可能。リリースビルドでは完全にコンパイル除去されるため、本番環境でのパフォーマンスへの影響がゼロ。Visual Studio Diagnostic Tools、Application Insights、Event Tracing for Windows (ETW)との統合により、包括的なアプリケーション監視エコシステムを構築できます。
主な特徴
- 標準組み込み: .NET Framework/.NET Coreに標準搭載、追加依存なし
- 条件付きコンパイル: デバッグビルドのみ有効、リリースで自動除去
- Visual Studio統合: IDEとの完璧な統合とリアルタイム診断
- トレースリスナー: カスタム出力先への柔軟なログ転送
- パフォーマンス監視: CPU使用率、メモリ、スレッド状態の詳細分析
- ETW統合: Windows Event Tracingとの高度な連携機能
メリット・デメリット
メリット
- .NET標準ライブラリのため追加インストール・設定不要の即座利用
- 条件付きコンパイルによる本番環境での完全なパフォーマンス影響ゼロ
- Visual Studioとの完璧な統合による最高の開発者体験
- Microsoft エコシステム(Azure、Application Insights)との自然な連携
- 学習コストが最小限で .NET 開発者なら即座に活用可能
- Windows Event Tracingによる高度なシステム監視機能
デメリット
- 主にデバッグ用途のため、本格的なアプリケーションログには不向き
- 構造化ログやフィルタリング機能が他専用ライブラリより限定的
- クロスプラットフォーム環境では一部機能が制限される場合あり
- 大規模分散システムでの包括的ログ管理には専用ソリューション必要
- 設定オプションが限定的で高度なカスタマイズが困難
- ログローテーションや永続化機能の自動サポートが限定的
参考ページ
書き方の例
インストール・セットアップ
// .NET Framework/.NET Core標準ライブラリのため追加インストール不要
using System;
using System.Diagnostics;
namespace DebuggingExample
{
class Program
{
static void Main(string[] args)
{
// 基本的な動作確認
Debug.WriteLine("System.Diagnostics.Debug is ready to use!");
Console.WriteLine("Debug output configured successfully");
}
}
}
<!-- プロジェクトファイル(.csproj) - 診断機能の設定 -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<!-- デバッグビルドでのDEBUGシンボル有効化 -->
<DefineConstants Condition="'$(Configuration)' == 'Debug'">DEBUG;TRACE</DefineConstants>
<!-- リリースビルドでのTRACEのみ有効化 -->
<DefineConstants Condition="'$(Configuration)' == 'Release'">TRACE</DefineConstants>
</PropertyGroup>
</Project>
基本的なログ出力
using System;
using System.Diagnostics;
using System.Collections.Generic;
public class BasicDebuggingExample
{
public static void DemonstrateBasicDebugging()
{
// 基本的なデバッグ出力
Debug.WriteLine("=== 基本的なデバッグ出力 ===");
Debug.WriteLine("アプリケーション開始");
Debug.WriteLine($"現在時刻: {DateTime.Now}");
// フォーマット付きデバッグ出力
string userName = "田中太郎";
int userId = 12345;
Debug.WriteLine($"ユーザー情報: ID={userId}, 名前={userName}");
Debug.WriteLine("ユーザー {0} (ID: {1}) がログインしました", userName, userId);
// 条件付きデバッグ出力
bool isDevelopmentMode = true;
Debug.WriteLineIf(isDevelopmentMode, "開発モードで実行中");
// インデント付きデバッグ出力(階層表示)
Debug.WriteLine("メイン処理開始");
Debug.Indent();
Debug.WriteLine("サブ処理1実行");
Debug.Indent();
Debug.WriteLine("詳細処理実行中...");
Debug.Unindent();
Debug.WriteLine("サブ処理1完了");
Debug.Unindent();
Debug.WriteLine("メイン処理完了");
// アサーション(条件チェック)
int result = CalculateSum(5, 3);
Debug.Assert(result == 8, $"計算結果が期待値と異なります。期待値: 8, 実際値: {result}");
// オブジェクトの状態出力
var user = new User { Id = 123, Name = "山田花子", Email = "[email protected]" };
Debug.WriteLine($"ユーザーオブジェクト: {user}");
// コレクションの内容出力
var numbers = new List<int> { 1, 2, 3, 4, 5 };
Debug.WriteLine($"数値リスト: [{string.Join(", ", numbers)}]");
// 例外情報の出力
try
{
int divResult = 10 / 0;
}
catch (DivideByZeroException ex)
{
Debug.WriteLine($"例外発生: {ex.GetType().Name}");
Debug.WriteLine($"メッセージ: {ex.Message}");
Debug.WriteLine($"スタックトレース: {ex.StackTrace}");
}
// パフォーマンス測定
var stopwatch = Stopwatch.StartNew();
PerformSomeWork();
stopwatch.Stop();
Debug.WriteLine($"処理時間: {stopwatch.ElapsedMilliseconds}ms");
}
private static int CalculateSum(int a, int b)
{
Debug.WriteLine($"計算実行: {a} + {b}");
return a + b;
}
private static void PerformSomeWork()
{
Debug.WriteLine("何らかの作業を実行中...");
System.Threading.Thread.Sleep(100);
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public override string ToString()
{
return $"User{{Id={Id}, Name='{Name}', Email='{Email}'}}";
}
}
}
ログレベル設定
using System;
using System.Diagnostics;
public class DebugLevelConfiguration
{
// カスタムデバッグレベルの実装
public enum DebugLevel
{
None = 0,
Error = 1,
Warning = 2,
Info = 3,
Debug = 4,
Trace = 5
}
private static DebugLevel currentLevel = DebugLevel.Debug;
public static void SetDebugLevel(DebugLevel level)
{
currentLevel = level;
Debug.WriteLine($"デバッグレベルを {level} に設定しました");
}
public static void LogError(string message)
{
if (currentLevel >= DebugLevel.Error)
{
Debug.WriteLine($"[ERROR] {DateTime.Now:HH:mm:ss.fff} {message}");
}
}
public static void LogWarning(string message)
{
if (currentLevel >= DebugLevel.Warning)
{
Debug.WriteLine($"[WARN] {DateTime.Now:HH:mm:ss.fff} {message}");
}
}
public static void LogInfo(string message)
{
if (currentLevel >= DebugLevel.Info)
{
Debug.WriteLine($"[INFO] {DateTime.Now:HH:mm:ss.fff} {message}");
}
}
public static void LogDebug(string message)
{
if (currentLevel >= DebugLevel.Debug)
{
Debug.WriteLine($"[DEBUG] {DateTime.Now:HH:mm:ss.fff} {message}");
}
}
public static void LogTrace(string message)
{
if (currentLevel >= DebugLevel.Trace)
{
Debug.WriteLine($"[TRACE] {DateTime.Now:HH:mm:ss.fff} {message}");
}
}
public static void DemonstrateLevels()
{
SetDebugLevel(DebugLevel.Warning);
LogError("これはエラーメッセージです"); // 表示される
LogWarning("これは警告メッセージです"); // 表示される
LogInfo("これは情報メッセージです"); // 表示されない
LogDebug("これはデバッグメッセージです"); // 表示されない
LogTrace("これはトレースメッセージです"); // 表示されない
SetDebugLevel(DebugLevel.Trace);
LogError("エラー: データベース接続失敗");
LogWarning("警告: メモリ使用量が高くなっています");
LogInfo("情報: ユーザーがログインしました");
LogDebug("デバッグ: SQL実行 - SELECT * FROM Users");
LogTrace("トレース: メソッド開始 - UserService.GetUser()");
}
}
.NET固有機能
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
public class DotNetSpecificFeatures
{
public static void DemonstrateAdvancedFeatures()
{
// 条件付きメソッド(DEBUGシンボル定義時のみ実行)
PerformDebugOnlyOperation();
// カスタムトレースリスナーの設定
SetupCustomTraceListener();
// パフォーマンスカウンターの使用
DemonstratePerformanceCounters();
// 非同期処理でのデバッグ
DemonstrateAsyncDebugging().Wait();
// LINQ式でのデバッグ
DemonstrateLINQDebugging();
// プロセス情報の取得
DemonstrateProcessInformation();
}
[Conditional("DEBUG")]
public static void PerformDebugOnlyOperation()
{
Debug.WriteLine("この処理はDEBUGビルドでのみ実行されます");
// 詳細なメモリ情報の表示
var process = Process.GetCurrentProcess();
Debug.WriteLine($"プロセス名: {process.ProcessName}");
Debug.WriteLine($"作業セット: {process.WorkingSet64 / 1024 / 1024} MB");
Debug.WriteLine($"仮想メモリ: {process.VirtualMemorySize64 / 1024 / 1024} MB");
Debug.WriteLine($"GCメモリ: {GC.GetTotalMemory(false) / 1024 / 1024} MB");
}
public static void SetupCustomTraceListener()
{
Debug.WriteLine("カスタムトレースリスナーの設定");
// ファイルトレースリスナーの追加
var fileListener = new TextWriterTraceListener("debug.log");
Debug.Listeners.Add(fileListener);
// コンソールトレースリスナーの追加
var consoleListener = new ConsoleTraceListener();
Debug.Listeners.Add(consoleListener);
Debug.WriteLine("複数出力先に同時出力されています");
// リスナーの削除
Debug.Listeners.Remove(fileListener);
Debug.Listeners.Remove(consoleListener);
// ファイルクリーンアップ
fileListener.Close();
}
public static void DemonstratePerformanceCounters()
{
Debug.WriteLine("=== パフォーマンス監視 ===");
var process = Process.GetCurrentProcess();
Debug.WriteLine($"CPU使用時間: {process.TotalProcessorTime.TotalMilliseconds}ms");
Debug.WriteLine($"ユーザーCPU時間: {process.UserProcessorTime.TotalMilliseconds}ms");
Debug.WriteLine($"システムCPU時間: {process.PrivilegedProcessorTime.TotalMilliseconds}ms");
Debug.WriteLine($"スレッド数: {process.Threads.Count}");
Debug.WriteLine($"ハンドル数: {process.HandleCount}");
// GC情報の表示
for (int generation = 0; generation <= GC.MaxGeneration; generation++)
{
Debug.WriteLine($"GC Gen{generation} コレクション回数: {GC.CollectionCount(generation)}");
}
}
public static async Task DemonstrateAsyncDebugging()
{
Debug.WriteLine("=== 非同期処理デバッグ ===");
var tasks = new List<Task>();
for (int i = 0; i < 3; i++)
{
int taskId = i;
var task = Task.Run(async () =>
{
Debug.WriteLine($"タスク {taskId} 開始 - スレッドID: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(100 * (taskId + 1));
Debug.WriteLine($"タスク {taskId} 完了 - スレッドID: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
return taskId * 10;
});
tasks.Add(task);
}
Debug.WriteLine("全タスクの完了を待機中...");
await Task.WhenAll(tasks);
Debug.WriteLine("全タスク完了");
}
public static void DemonstrateLINQDebugging()
{
Debug.WriteLine("=== LINQ式デバッグ ===");
var numbers = Enumerable.Range(1, 10).ToList();
Debug.WriteLine($"元データ: [{string.Join(", ", numbers)}]");
var result = numbers
.Where(n => {
Debug.WriteLine($"フィルタ処理: {n}");
return n % 2 == 0;
})
.Select(n => {
Debug.WriteLine($"変換処理: {n} -> {n * n}");
return n * n;
})
.OrderByDescending(n => {
Debug.WriteLine($"ソート処理: {n}");
return n;
})
.ToList();
Debug.WriteLine($"最終結果: [{string.Join(", ", result)}]");
}
public static void DemonstrateProcessInformation()
{
Debug.WriteLine("=== プロセス情報 ===");
var currentProcess = Process.GetCurrentProcess();
Debug.WriteLine($"プロセスID: {currentProcess.Id}");
Debug.WriteLine($"プロセス名: {currentProcess.ProcessName}");
Debug.WriteLine($"開始時刻: {currentProcess.StartTime}");
Debug.WriteLine($"実行時間: {DateTime.Now - currentProcess.StartTime}");
Debug.WriteLine($"優先度: {currentProcess.BasePriority}");
Debug.WriteLine($"メインモジュール: {currentProcess.MainModule?.FileName}");
// 環境変数の表示(一部)
Debug.WriteLine("=== 環境変数(抜粋) ===");
var envVars = new[] { "OS", "PROCESSOR_ARCHITECTURE", "NUMBER_OF_PROCESSORS" };
foreach (var envVar in envVars)
{
Debug.WriteLine($"{envVar}: {Environment.GetEnvironmentVariable(envVar)}");
}
// アセンブリ情報の表示
Debug.WriteLine("=== アセンブリ情報 ===");
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
Debug.WriteLine($"アセンブリ名: {assembly.FullName}");
Debug.WriteLine($"場所: {assembly.Location}");
Debug.WriteLine($"ランタイムバージョン: {assembly.ImageRuntimeVersion}");
}
}
設定ファイル例
<!-- app.config / web.config - システム診断設定 -->
<configuration>
<system.diagnostics>
<!-- トレースリスナーの設定 -->
<trace autoflush="true" indentsize="4">
<listeners>
<!-- コンソール出力 -->
<add name="consoleListener"
type="System.Diagnostics.ConsoleTraceListener" />
<!-- ファイル出力 -->
<add name="fileListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="debug.log" />
<!-- イベントログ出力 -->
<add name="eventLogListener"
type="System.Diagnostics.EventLogTraceListener"
initializeData="Application" />
<!-- カスタムリスナー -->
<add name="customListener"
type="MyApp.CustomTraceListener, MyApp" />
</listeners>
</trace>
<!-- デバッグリスナーの設定 -->
<debug autoflush="true">
<listeners>
<add name="debugFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="debug-only.log" />
</listeners>
</debug>
<!-- ソース別トレース設定 -->
<sources>
<source name="MyApp.UserService" switchValue="Verbose">
<listeners>
<add name="userServiceLog"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="userservice.log" />
</listeners>
</source>
<source name="MyApp.DataAccess" switchValue="Warning">
<listeners>
<add name="dataAccessLog"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="dataaccess.log" />
</listeners>
</source>
</sources>
<!-- スイッチ設定 -->
<switches>
<add name="GeneralSwitch" value="4" />
<add name="DatabaseSwitch" value="2" />
</switches>
</system.diagnostics>
</configuration>
パフォーマンス最適化
using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
public class DebugPerformanceOptimization
{
public static void OptimizedDebuggingExamples()
{
// 1. 条件付きコンパイル属性の活用
DebugOnlyExpensiveOperation();
// 2. 遅延評価による最適化
DemonstrateLazyEvaluation();
// 3. バッチ出力による最適化
DemonstrateBatchDebugging();
// 4. 構造化デバッグ情報
DemonstrateStructuredDebugging();
// 5. メモリ効率的なデバッグ
DemonstrateMemoryEfficientDebugging();
}
[Conditional("DEBUG")]
public static void DebugOnlyExpensiveOperation()
{
Debug.WriteLine("=== 条件付きコンパイル最適化 ===");
// この処理はDEBUGビルドでのみ実行される
var stopwatch = Stopwatch.StartNew();
// 重い処理のシミュレーション
PerformExpensiveCalculation();
stopwatch.Stop();
Debug.WriteLine($"重い処理完了: {stopwatch.ElapsedMilliseconds}ms");
// リリースビルドでは上記のコードは完全に除去される
}
public static void DemonstrateLazyEvaluation()
{
Debug.WriteLine("=== 遅延評価最適化 ===");
// 非効率な例(常に文字列生成)
var data = GenerateExpensiveString();
Debug.WriteLineIf(IsDebugEnabled(), $"データ: {data}");
// 効率的な例(必要時のみ生成)
if (IsDebugEnabled())
{
var lazyData = GenerateExpensiveString();
Debug.WriteLine($"遅延データ: {lazyData}");
}
// ラムダ式を使った遅延評価
DebugWriteIf(IsDebugEnabled(), () => $"ラムダデータ: {GenerateExpensiveString()}");
}
public static void DemonstrateBatchDebugging()
{
Debug.WriteLine("=== バッチ出力最適化 ===");
var batchOutput = new StringBuilder();
// 個別出力(非効率)
for (int i = 0; i < 5; i++)
{
Debug.WriteLine($"個別出力 {i}");
}
// バッチ出力(効率的)
for (int i = 0; i < 5; i++)
{
batchOutput.AppendLine($"バッチ項目 {i}");
}
Debug.WriteLine("=== バッチ結果 ===");
Debug.WriteLine(batchOutput.ToString());
}
public static void DemonstrateStructuredDebugging()
{
Debug.WriteLine("=== 構造化デバッグ ===");
var user = new { Id = 123, Name = "田中太郎", Email = "[email protected]" };
var timestamp = DateTime.Now;
// 構造化されたデバッグ情報
Debug.WriteLine($"{{\"timestamp\":\"{timestamp:o}\", \"event\":\"user_action\", \"user_id\":{user.Id}, \"user_name\":\"{user.Name}\"}}");
// タブ区切り形式
Debug.WriteLine($"{timestamp:yyyy-MM-dd HH:mm:ss.fff}\\t{user.Id}\\t{user.Name}\\tログイン");
// カスタム構造化出力
WriteStructuredDebug("USER_LOGIN", new {
UserId = user.Id,
UserName = user.Name,
Timestamp = timestamp,
Success = true
});
}
public static void DemonstrateMemoryEfficientDebugging()
{
Debug.WriteLine("=== メモリ効率最適化 ===");
// 効率的な文字列フォーマット
var userId = 12345;
var userName = "田中太郎";
// string.Concat より効率的
Debug.WriteLine($"ユーザー: {userId} - {userName}");
// 大きなオブジェクトの場合は要約のみ
var largeArray = new int[10000];
Debug.WriteLine($"配列情報: 長さ={largeArray.Length}, ハッシュ={largeArray.GetHashCode()}");
// StringBuilderの使い回し
var sb = new StringBuilder(256);
for (int i = 0; i < 3; i++)
{
sb.Clear();
sb.Append("処理 ").Append(i).Append(" - ").Append(DateTime.Now.Millisecond);
Debug.WriteLine(sb.ToString());
}
}
// ヘルパーメソッド
private static bool IsDebugEnabled()
{
#if DEBUG
return true;
#else
return false;
#endif
}
private static void DebugWriteIf(bool condition, Func<string> messageProvider)
{
if (condition)
{
Debug.WriteLine(messageProvider());
}
}
private static string GenerateExpensiveString()
{
// 重い処理のシミュレーション
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
sb.Append($"item_{i},");
}
return sb.ToString().TrimEnd(',');
}
private static void PerformExpensiveCalculation()
{
// CPU集約的な処理のシミュレーション
double result = 0;
for (int i = 0; i < 1000000; i++)
{
result += Math.Sqrt(i);
}
}
private static void WriteStructuredDebug(string eventName, object data)
{
var json = System.Text.Json.JsonSerializer.Serialize(new {
Event = eventName,
Timestamp = DateTime.UtcNow,
Data = data
});
Debug.WriteLine($"STRUCTURED: {json}");
}
}