DebugUtils.CSharp
1.6.0
See the version list below for details.
dotnet add package DebugUtils.CSharp --version 1.6.0
NuGet\Install-Package DebugUtils.CSharp -Version 1.6.0
<PackageReference Include="DebugUtils.CSharp" Version="1.6.0" />
<PackageVersion Include="DebugUtils.CSharp" Version="1.6.0" />
<PackageReference Include="DebugUtils.CSharp" />
paket add DebugUtils.CSharp --version 1.6.0
#r "nuget: DebugUtils.CSharp, 1.6.0"
#:package DebugUtils.CSharp@1.6.0
#addin nuget:?package=DebugUtils.CSharp&version=1.6.0
#tool nuget:?package=DebugUtils.CSharp&version=1.6.0
DebugUtils for C#
A collection of debugging utilities for C# developers.
Core Features
đ Object Representation (Repr, ReprTree Documentation)
Stop getting useless ToString() output. See actual object contents.
đ Call Stack Tracking (CallStack Documentation)
Know exactly where your code is executing and which methods are calling what.
Installation
Add this project as a reference or copy the source files to your project.
Quick Start
using DebugUtils.CallStack;
using DebugUtils.Repr;
// đ Better object representation
var data = new { Name = "Alice", Age = 30, Scores = new[] {95, 87, 92} };
Console.WriteLine(data.Repr());
// Output: Anonymous(Age: int(30), Name: "Alice", Scores: 1DArray([int(95), int(87), int(92)]))
// đŗ Structured tree output for complex analysis
Console.WriteLine(data.ReprTree());
// Output: {
// "type": "Anonymous",
// "kind": "class",
// "hashCode": "0xAAAAAAAA",
// "Age": { "type": "int", "kind": "struct", "value": "30" },
// "Name": { "type": "string", "kind": "class", "hashCode": "0xBBBBBBBB", "length": 5, "value": "Alice" },
// "Scores": {
// "type": "1DArray",
// "kind": "class",
// "hashCode": "0xCCCCCCCC",
// "rank": 1,
// "dimensions": [3],
// "elementType": "int",
// "value": [
// { "type": "int", "kind": "struct", "value": "95" },
// { "type": "int", "kind": "struct", "value": "87" },
// { "type": "int", "kind": "struct", "value": "92" }
// ]
// }
// } (hashCode may vary.)
// đ Caller tracking for debugging
public class Program
{
public void MyAlgorithm()
{
Console.WriteLine($"[{CallStack.GetCallerName()}] Starting algorithm...");
var result = ComputeResult();
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Result: {result.Repr()}");
}
}
// Output: [Program.MyAlgorithm] Starting algorithm...
// Output: [Program.MyAlgorithm@Program.cs:21:8] Result: [int(1), int(4), int(9), int(16), int(25)]
Features
đ Object Representation (.Repr())
Works with any type - see actual data instead of useless type names.
Collections
// Arrays (1D, 2D, jagged)
new[] {1, 2, 3}.Repr() // 1DArray([int(1), int(2), int(3)])
new[,] {{1, 2}, {3, 4}}.Repr() // 2DArray([[int(1), int(2)], [int(3), int(4)]])
new[][] {{1, 2}, {3, 4, 5}}.Repr() // JaggedArray([[int(1), int(2)], [int(3), int(4), int(5)]])
// Lists, Sets, Dictionaries
new List<int> {1, 2, 3}.Repr() // [int(1), int(2), int(3)]
new HashSet<string> {"a", "b"}.Repr() // {"a", "b"}
new Dictionary<string, int> {{"x", 1}}.Repr() // {"x": int(1)}
Numeric Types
// Integers with different representations
42.Repr() // int(42)
42.Repr(new ReprConfig(IntFormatString: "X")) // int(0x2A)
42.Repr(new ReprConfig(IntFormatString: "B")) // int(0b101010)
42.Repr(new ReprConfig(IntFormatString: "HB")) // int(0x0000002A) - hex bytes
// Floating point with exact representation
// You can now recognize the real floating point value
// and find what went wrong when doing arithmetics!
(0.1 + 0.2).Repr()
// double(3.00000000000000444089209850062616169452667236328125E-001)
0.3.Repr()
// double(2.99999999999999988897769753748434595763683319091796875E-001)
(0.1 + 0.2).Repr(new ReprConfig(FloatFormatString: "G"))
// double(0.30000000000000004)
// New special formatting modes
3.14f.Repr(new ReprConfig(FloatFormatString: "BF")) // IEEE 754 bit field
3.14f.Repr(new ReprConfig(FloatFormatString: "HB")) // Raw hex bytes
đ Caller Method Tracking (GetCallerName())
Perfect for logging, error tracking, and debugging call flows:
// DataProcessor.cs
public class DataProcessor
{
public void ProcessFile(string filename)
{
var caller = CallStack.GetCallerName();
Console.WriteLine($"[{caller}] Processing file: {filename}");
if (!File.Exists(filename))
{
Console.WriteLine($"[{caller}] ERROR: File not found");
return;
}
try
{
var data = LoadData(filename);
Console.WriteLine($"[{caller}] Loaded {data.Length} records");
}
catch (Exception ex)
{
Console.WriteLine($"[{caller}] FAILED: {ex.Message}");
throw;
}
}
}
// Output: [DataProcessor.ProcessFile] Processing file: data.txt
// Output: [DataProcessor.ProcessFile] Loaded 150 records
âšī¸ Detailed Caller Information (GetCallerInfo())
Get the file, line, and column number for even more precise debugging.
// DataProcessor.cs
public class DataProcessor
{
public void ProcessFile(string filename)
{
var caller = CallStack.GetCallerInfo();
Console.WriteLine($"[{caller}] Processing file: {filename}");
if (!File.Exists(filename))
{
Console.WriteLine($"[{caller}] ERROR: File not found");
return;
}
}
}
// Output: [DataProcessor.ProcessFile@DataProcessor.cs:6:8] Processing file: data.txt
Use cases:
- Error tracking - Know the exact line that failed
- Performance logging - Pinpoint slow sections of code
- Debugging algorithms - Trace execution flow with precision
- Unit testing - Get detailed failure locations
Member Ordering (v1.6)
For object representation, DebugUtils uses deterministic alphabetical ordering within member categories:
- Public fields (alphabetical by name)
- Public auto-properties (alphabetical by name)
- Private fields (alphabetical by name, prefixed with "private_")
- Private auto-properties (alphabetical by name, prefixed with "private_")
public class ClassifiedData
{
public long Id = 5; // Category 1: Public field
public int Age = 10; // Category 1: Public field
public string Writer { get; set; } // Category 2: Public auto-property
public string Name { get; set; } // Category 2: Public auto-property
private DateTime Date = DateTime.Now; // Category 3: Private field
private string Password = "secret"; // Category 3: Private field
private string Data { get; set; } // Category 4: Private auto-property
private Guid Key { get; set; } // Category 4: Private auto-property
}
// Output with ShowNonPublicProperties: true
// ClassifiedData(Age: int(10), Id: long(5), Name: "Alice", Writer: "Bob",
// private_Date: DateTime(...), private_Password: "secret",
// private_Data: "info", private_Key: Guid(...))
This ordering ensures deterministic output while grouping similar member types together. Auto-properties are accessed via their backing fields to avoid potential side effects from getter calls.
Configuration Options
Float Formatting (NEW: Format Strings)
// NEW APPROACH: Format strings (recommended)
var exact = new ReprConfig(FloatFormatString: "EX");
3.14159.Repr(exact); // Exact decimal representation down to very last digit
var scientific = new ReprConfig(FloatFormatString: "E5");
3.14159.Repr(scientific); // Scientific notation with 5 decimal places
var rounded = new ReprConfig(FloatFormatString: "F2");
3.14159.Repr(rounded); // Fixed point with 2 decimal places
// Special debugging modes
var bitField = new ReprConfig(FloatFormatString: "BF");
3.14f.Repr(bitField); // IEEE 754 bit field: 0|10000000|10010001111010111000011
var hexBytes = new ReprConfig(FloatFormatString: "HB");
3.14f.Repr(hexBytes); // Raw hex bytes: 0x4048F5C3
// OLD APPROACH: Enum modes (deprecated but still supported)
var oldExact = new ReprConfig(FloatMode: FloatReprMode.Exact);
var oldRounded = new ReprConfig(FloatMode: FloatReprMode.Round, FloatPrecision: 2);
Integer Formatting (NEW: Format Strings)
// NEW APPROACH: Format strings (recommended)
var hex = new ReprConfig(IntFormatString: "X");
255.Repr(hex); // Hexadecimal: int(0xFF)
var binary = new ReprConfig(IntFormatString: "B");
255.Repr(binary); // Binary: int(0b11111111)
var hexBytes = new ReprConfig(IntFormatString: "HB");
255.Repr(hexBytes); // Hex bytes: int(0x000000FF)
var decimal = new ReprConfig(IntFormatString: "D");
255.Repr(decimal); // Standard decimal: int(255)
// OLD APPROACH: Enum modes (deprecated but still supported)
var oldHex = new ReprConfig(IntMode: IntReprMode.Hex);
var oldBinary = new ReprConfig(IntMode: IntReprMode.Binary);
Type Display
var hideTypes = new ReprConfig(
TypeMode: TypeReprMode.AlwaysHide,
ContainerReprMode: ContainerReprMode.UseParentConfig
);
new[] {1, 2, 3}.Repr(hideTypes); // [1, 2, 3] (no type prefix to child element.)
var showTypes = new ReprConfig(TypeMode: TypeReprMode.AlwaysShow);
new[] {1, 2, 3}.Repr(showTypes); // 1DArray([int(1), int(2), int(3)])
Hierarchical Display
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
var a = new Person(name: "Lumi", age: 28);
a.ReprTree();
// Output: {
// "type": "Person",
// "kind": "class",
// "hashCode": "0xAAAAAAAA",
// "Age": {"type": "int", "kind": "struct", "value": "28"},
// "Name": {"type": "string", "kind": "class", "hashCode": "0xBBBBBBBB", "length": 4, "value": "Lumi"}
// } (hashCode may vary)
Real-World Use Cases
Competitive Programming
Debug algorithms instantly without writing custom debug code:
// Debug your DP table
int[,] dp = new int[n, m];
// ... fill DP table ...
Console.WriteLine($"[{CallStack.GetCallerInfo()}] DP: {dp.Repr()}");
// Track algorithm execution
public int Solve(int[] arr)
{
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Input: {arr.Repr()}");
var result = ProcessArray(arr);
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Result: {result}");
return result;
}
Production Debugging
public async Task<ApiResponse> ProcessRequest(RequestData request)
{
var caller = CallStack.GetCallerInfo();
logger.Info($"[{caller}] Request: {request.Repr()}");
try
{
var response = await ProcessData(request.Data);
logger.Info($"[{caller}] Success: {response.Repr()}");
return response;
}
catch (Exception ex)
{
logger.Error($"[{caller}] Failed processing: {ex.Message}");
logger.Error($"[{caller}] Request data: {request.Repr()}");
throw;
}
}
Unit Testing
[Fact]
public void TestComplexAlgorithm()
{
var input = GenerateTestData();
var expected = CalculateExpected(input);
var actual = MyAlgorithm(input);
// Amazing error messages when tests fail
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Input: {input.Repr()}");
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Expected: {expected.Repr()}");
Console.WriteLine($"[{CallStack.GetCallerInfo()}] Actual: {actual.Repr()}");
Assert.Equal(expected, actual);
}
Target Frameworks
- .NET 6.0 (compatible with BOJ and older systems)
- .NET 7.0 (includes Int128 support, compatible with AtCoder)
- .NET 8.0
- .NET 9.0 (compatible with Codeforces)
Roadmap
Current Features:
â
.Repr() - Comprehensive object representation
â
.ReprTree() - Structured JSON tree output
â
.FormatAsJsonNode() - Custom formatter building blocks
â
GetCallerName() - Simple call stack tracking
â
GetCallerInfo() - Detailed call stack tracking
â
NEW in v1.5: Format string-based numeric formatting (FloatFormatString, IntFormatString)
â
NEW in v1.5: Special debugging modes (EX, HB, BF, B)
â
NEW in v1.5: Enhanced time formatting with tick-level precision
â
Multi-framework support (.NET 6-9)
â
Zero dependencies
â
Circular reference detection
â
Custom formatter system
Planned Features:
- đ Performance profiling utilities
- đ Memory usage tracking
- đ Advanced logging helpers
- đ Unity debugging extensions
- đ Benchmark timing utilities
This library started as a solution to competitive programming debugging but is growing into a comprehensive debugging toolkit.
Contributing
Built out of frustration with C# debugging pain points. If you have ideas for additional debugging utilities or find bugs, contributions are welcome!
Ideas for new features:
- Timer/stopwatch utilities for performance testing
- Memory allocation tracking
- Advanced stack trace analysis
- Custom assertion helpers
License
This project follows MIT license.
Stop debugging blind. See your actual data with crystal clarity and know exactly where your code executes. đ¯
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.8.2 | 222 | 11/15/2025 |
| 1.8.1 | 273 | 11/14/2025 |
| 1.8.0 | 410 | 8/20/2025 |
| 1.7.0 | 205 | 8/18/2025 |
| 1.6.0 | 208 | 8/13/2025 |
| 1.5.0 | 207 | 8/13/2025 |
| 1.4.0 | 221 | 8/12/2025 |
| 1.3.2 | 190 | 8/11/2025 |
| 1.3.1 | 191 | 8/11/2025 |
| 1.3.0 | 190 | 8/10/2025 |
| 1.2.5 | 194 | 8/9/2025 |
| 1.2.4 | 193 | 8/9/2025 |
| 1.2.3 | 276 | 8/8/2025 |
| 1.2.2 | 282 | 8/7/2025 |
| 1.2.1 | 277 | 8/7/2025 |
| 1.2.0 | 264 | 8/7/2025 |
| 1.1.0 | 267 | 8/6/2025 |
| 1.0.3 | 223 | 8/4/2025 |
| 1.0.2 | 170 | 8/3/2025 |
| 1.0.1 | 108 | 8/2/2025 |
See CHANGELOG.md for detailed release notes: https://github.com/dj-lumiere/DebugUtils-CSharp/blob/main/CHANGELOG.md