Meziantou.Framework.TextDiff 3.0.3

Prefix Reserved
dotnet add package Meziantou.Framework.TextDiff --version 3.0.3
                    
NuGet\Install-Package Meziantou.Framework.TextDiff -Version 3.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Meziantou.Framework.TextDiff" Version="3.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Meziantou.Framework.TextDiff" Version="3.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Meziantou.Framework.TextDiff" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Meziantou.Framework.TextDiff --version 3.0.3
                    
#r "nuget: Meziantou.Framework.TextDiff, 3.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Meziantou.Framework.TextDiff@3.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Meziantou.Framework.TextDiff&version=3.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Meziantou.Framework.TextDiff&version=3.0.3
                    
Install as a Cake Tool

Meziantou.Framework.TextDiff

Compute text differences at line, word, or character level with configurable comparison options.

Install the NuGet package Meziantou.Framework.TextDiff (NuGet)

dotnet package add Meziantou.Framework.TextDiff

Basic usage

var oldText = "line1\nline2\nline3";
var newText = "line1\nline2 updated\nline3";

var result = TextDiff.ComputeDiff(oldText, newText);

foreach (var entry in result.Entries)
{
    Console.WriteLine($"{entry.Operation}: {entry.Text}");
}

Rebuild either side of the diff

Text is the chunk from the old text (from the new text for an Insert). When a comparison option such as IgnoreCase makes two different chunks compare equal, OldText and NewText give the exact chunk from each side:

var oldText = string.Concat(result.Entries
    .Where(e => e.Operation is TextDiffOperation.Equal or TextDiffOperation.Delete)
    .Select(e => e.OldText));

var newText = string.Concat(result.Entries
    .Where(e => e.Operation is TextDiffOperation.Equal or TextDiffOperation.Insert)
    .Select(e => e.NewText));

Configure chunking and comparison

var options = new TextDiffOptions
{
    Chunker = TextChunker.Words,        // Lines (default), Words, Characters, or custom chunker
    IgnoreCase = true,
    IgnoreWhitespace = true,
    IgnoreEndOfLine = true,
};

var result = TextDiff.ComputeDiff("Hello   world\r\n", "hello world\n", options);
// result.HasDifferences == false

IgnoreWhitespace trims the edges of each chunk; whitespace inside a chunk stays significant. Chunker = TextChunker.Words is what makes the two texts above compare equal: it puts each run of whitespace in its own chunk, which trimming then reduces to an empty one. With the default TextChunker.Lines, "Hello world" and "hello world" are a single chunk each and still differ.

IgnoreEndOfLine normalizes line terminators before chunking, so the entries of the result carry \n rather than the original \r\n.

Compute a hierarchical diff with multiple chunking levels

var result = TextDiff.ComputeHierarchyDiff(
    oldText: "line1\nhello world\nline3",
    newText: "line1\nhello brave world\nline3",
    chunkers: [TextChunker.Lines, TextChunker.Words, TextChunker.Characters]);

foreach (var entry in result.Entries)
{
    Console.WriteLine($"{entry.Operation}: old={entry.OldText} new={entry.NewText}");

    foreach (var child in entry.Children)
    {
        Console.WriteLine($"  {child.Operation}: old={child.OldText} new={child.NewText}");
    }
}

The hierarchy API lets you refine changed chunks progressively (Lines -> Words -> Characters, Words -> Characters, etc.).

Choose a diff algorithm

var options = new TextDiffOptions
{
    Algorithm = TextDiffAlgorithm.Patience,
};

var result = TextDiff.ComputeDiff(oldText, newText, options);

Available algorithms:

  • TextDiffAlgorithm.Myers (default): best default when you want a high-quality, shortest-edit-script style diff.
  • TextDiffAlgorithm.Patience: best for human-readable output in reviews, even if edits are not always minimal.
  • TextDiffAlgorithm.Histogram: good practical choice for large or repetitive texts when performance is important.
  • TextDiffAlgorithm.HuntSzymanski: useful for large inputs with relatively sparse matches.

Cost

All four algorithms trim the common prefix and suffix first, so the cost below is driven by the part that actually differs — two revisions of the same file are cheap whatever you pick.

Algorithm Cost Degrades when
Myers O(D²), D = edit distance the two texts have little in common: 50 000 fully different lines take seconds
Patience anchor search, Myers on unanchored regions no chunk is unique, so it falls back to Myers
Histogram anchor search, Myers on unanchored regions every shared chunk is very frequent, so it falls back to Myers
HuntSzymanski O(r log n), r = matching pairs many duplicate chunks, which makes r quadratic

There is no work limit: a diff of two large, unrelated texts runs to completion however long it takes. Character-level diffs reach these sizes quickly, since every character is a chunk — prefer ComputeHierarchyDiff so the character diff only runs on chunks that already changed.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.  net11.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net11.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Meziantou.Framework.TextDiff:

Package Downloads
Meziantou.Framework.InlineSnapshotTesting

Enables verification of objects using inline snapshots

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.3 357 8/29/2026
3.0.2 1,002 8/23/2026
3.0.1 6,523 7/8/2026
3.0.0 802 7/5/2026
2.0.5 4,466 6/13/2026
2.0.4 4,541 5/31/2026
2.0.3 709 5/23/2026
2.0.2 1,436 5/14/2026
2.0.1 2,233 5/11/2026
2.0.0 793 5/6/2026
1.0.1 4,117 4/25/2026
1.0.0 662 4/4/2026