From 138e86877437204eb9d165d68ab9914ad094f2f7 Mon Sep 17 00:00:00 2001 From: Bruno Van Thournout <> Date: Mon, 8 Dec 2025 10:40:53 +0100 Subject: [PATCH 1/2] Add caching property and method --- ChangeLogs/1.0.3-ChangeLog.md | 13 ++++ ConsoleTable.Text.Examples/Program.cs | 2 + ConsoleTable.Text/Table.cs | 32 +++++++-- ConsoleTable.slnx | 1 + README.md | 2 + Tests/ConsoleTable.Text.Tests/TableTests.cs | 77 +++++++++++++++++++++ 6 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 ChangeLogs/1.0.3-ChangeLog.md diff --git a/ChangeLogs/1.0.3-ChangeLog.md b/ChangeLogs/1.0.3-ChangeLog.md new file mode 100644 index 0000000..b9a2c59 --- /dev/null +++ b/ChangeLogs/1.0.3-ChangeLog.md @@ -0,0 +1,13 @@ +# V1.0.3 + +## New Property + +| Property | Type | Default | Description | +|----------|------|---------|-------------| +| `CachingEabled` | `bool` | `true` |When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | + +## New Method + +| Method | Description | +|--------|-------------| +| `ClearCache()` | Clears the cached generated table string. | diff --git a/ConsoleTable.Text.Examples/Program.cs b/ConsoleTable.Text.Examples/Program.cs index d0771ce..082c2b7 100644 --- a/ConsoleTable.Text.Examples/Program.cs +++ b/ConsoleTable.Text.Examples/Program.cs @@ -54,6 +54,7 @@ private static void WriteDefaultTableWithProperties() var table = new Table { + CachingEabled = true, Headers = new string[] { "Name", "Age", "City" }, Rows = new List { @@ -156,6 +157,7 @@ private static void WriteTableWithStyling(bool headerTextAlignRight, bool rowTex var table = new Table { + CachingEabled = true, Padding = padding, HeaderTextAlignmentRight = headerTextAlignRight, RowTextAlignmentRight = rowTextAlignRight diff --git a/ConsoleTable.Text/Table.cs b/ConsoleTable.Text/Table.cs index 4db99d4..81f57cf 100644 --- a/ConsoleTable.Text/Table.cs +++ b/ConsoleTable.Text/Table.cs @@ -9,6 +9,23 @@ public class Table { private string _tableCache = null; + private bool _cachingEabled = true; + /// + /// Enables the caching of the generated table string when the ToTable method is called. Default is true. + /// Cache will be cleared on any property change or method call. + /// + public bool CachingEabled + { + get => _cachingEabled; + set + { + _cachingEabled = value; + + if (!_cachingEabled) + ClearCache(); + } + } + private string[] _headers = Array.Empty(); /// /// Gets or sets the headers of the table. This is a single optional top row. @@ -282,9 +299,13 @@ private StringBuilder CreateSeperatorLine(int[] maximumCellWidths, int previousR return formattedTable; } - private void ClearCache() + /// + /// Clears the cached generated table string + /// + public Table ClearCache() { _tableCache = null; + return this; } /// @@ -303,7 +324,7 @@ public Table Clear() /// public string ToTable() { - if (!string.IsNullOrEmpty(_tableCache)) + if (CachingEabled && !string.IsNullOrEmpty(_tableCache)) return _tableCache; var table = new List(); @@ -365,9 +386,12 @@ public string ToTable() formattedTable = CreateBottomLine(maximumCellWidths, previousRow.Count(), formattedTable); - _tableCache = formattedTable.ToString(); + var generatedTable = formattedTable.ToString(); + + if (CachingEabled) + _tableCache = generatedTable; - return _tableCache; + return generatedTable; } public override string ToString() diff --git a/ConsoleTable.slnx b/ConsoleTable.slnx index 1328dc0..717850d 100644 --- a/ConsoleTable.slnx +++ b/ConsoleTable.slnx @@ -7,6 +7,7 @@ + diff --git a/README.md b/README.md index c2fb267..b3b0075 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Output: | `Padding` | `int` | `1` | The number of spaces on each side of cell content | | `HeaderTextAlignmentRight` | `bool` | `false` | When `true`, header text is right-aligned otherwise left aligned | | `RowTextAlignmentRight` | `bool` | `false` | When `true`, row text is right-aligned otherwise left aligned | +| `CachingEabled` | `bool` | `true` | When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | ### Methods @@ -94,6 +95,7 @@ Output: | `AddRows(params string[][] rows)` | Adds multiple data rows to the table. Rows are not required. | | `ClearRows()` | Removes all data rows from the table (headers are preserved). | | `Clear()` | Clear all the headers and rows from the table. | +| `ClearCache()` | Clears the generated table string cache. This can be done to save memory. | | `ToTable() / ToString()` | Returns the formatted table as a string. | ## Examples diff --git a/Tests/ConsoleTable.Text.Tests/TableTests.cs b/Tests/ConsoleTable.Text.Tests/TableTests.cs index e9880ea..4fa8748 100644 --- a/Tests/ConsoleTable.Text.Tests/TableTests.cs +++ b/Tests/ConsoleTable.Text.Tests/TableTests.cs @@ -4,6 +4,46 @@ namespace ConsoleTable.Text.Tests; public class TableTests { + [Theory] + [InlineData(true)] + [InlineData(false)] + public void PerformanceCheck(bool cacheEnabled) + { + var table = new Table + { + CachingEabled = cacheEnabled, + HeaderTextAlignmentRight = true, + RowTextAlignmentRight = false, + Padding = 5 + }; + + var columnCount = 100; + var headers = new List(); + for (var i = 1; i <= columnCount; i++) + { + headers.Add($"Header{i}"); + } + table.Headers = headers.ToArray(); + + var rows = new List(); + for (var i = 0; i < 100000; i++) + { + var row = new string[columnCount]; + for (var j = 1; j <= columnCount; j++) + { + row[j - 1] = $"Row {i} -> Column {j}"; + } + rows.Add(row); + } + table.Rows = rows; + + var tableResult1 = table.ToTable(); + Assert.NotEmpty(tableResult1); + + var tableResult2 = table.ToTable(); + Assert.NotEmpty(tableResult2); + } + [Fact] public void ToTable_EmptyTable_ReturnsEmptyString() { @@ -555,6 +595,43 @@ public void AddRows_ClearsCache() Assert.Contains("NewRow", secondResult); } + [Fact] + public void ClearCache() + { + var table = new Table + { + CachingEabled = true + }; + + table.AddRow("1"); + var firstResult = table.ToTable(); + + table.ClearCache(); + var secondResult = table.ToTable(); + + Assert.Contains("1", firstResult); + Assert.Contains("1", secondResult); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CachingEnabled(bool cachingEnabled) + { + var table = new Table + { + CachingEabled = cachingEnabled + }; + + table.AddRow("1"); + + var firstResult = table.ToTable(); + var secondResult = table.ToTable(); + + Assert.Contains("1", firstResult); + Assert.Contains("1", secondResult); + } + [Fact] public void ToString_ReturnsFormattedTable() { From 5a299b59c8dc17874386e424a0ad7b55e84c4e2a Mon Sep 17 00:00:00 2001 From: Bruno Van Thournout <> Date: Mon, 8 Dec 2025 10:51:57 +0100 Subject: [PATCH 2/2] Fix typos + add big table example --- ChangeLogs/1.0.3-ChangeLog.md | 2 +- ConsoleTable.Text.Examples/Program.cs | 45 ++++++++++++++++++++- ConsoleTable.Text/Table.cs | 14 +++---- README.md | 2 +- Tests/ConsoleTable.Text.Tests/TableTests.cs | 16 ++++---- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/ChangeLogs/1.0.3-ChangeLog.md b/ChangeLogs/1.0.3-ChangeLog.md index b9a2c59..93dcaa8 100644 --- a/ChangeLogs/1.0.3-ChangeLog.md +++ b/ChangeLogs/1.0.3-ChangeLog.md @@ -4,7 +4,7 @@ | Property | Type | Default | Description | |----------|------|---------|-------------| -| `CachingEabled` | `bool` | `true` |When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | +| `CachingEnabled` | `bool` | `true` |When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | ## New Method diff --git a/ConsoleTable.Text.Examples/Program.cs b/ConsoleTable.Text.Examples/Program.cs index 082c2b7..b57ad4d 100644 --- a/ConsoleTable.Text.Examples/Program.cs +++ b/ConsoleTable.Text.Examples/Program.cs @@ -26,6 +26,8 @@ static void Main(string[] args) WriteTableFluent(); + WriteBigTable(); + Console.Read(); } @@ -54,7 +56,7 @@ private static void WriteDefaultTableWithProperties() var table = new Table { - CachingEabled = true, + CachingEnabled = true, Headers = new string[] { "Name", "Age", "City" }, Rows = new List { @@ -157,7 +159,7 @@ private static void WriteTableWithStyling(bool headerTextAlignRight, bool rowTex var table = new Table { - CachingEabled = true, + CachingEnabled = true, Padding = padding, HeaderTextAlignmentRight = headerTextAlignRight, RowTextAlignmentRight = rowTextAlignRight @@ -194,4 +196,43 @@ private static void WriteTableFluent() Console.WriteLine(tableString); Console.WriteLine(); } + + private static void WriteBigTable() + { + Console.WriteLine(); + Console.WriteLine("Big table (may take some seconds to generate):"); + + var table = new Table + { + CachingEnabled = true, + HeaderTextAlignmentRight = false, + RowTextAlignmentRight = false, + Padding = 2 + }; + + var columnCount = 5; + var headers = new List(); + for (var columnPos = 1; columnPos <= columnCount; columnPos++) + { + headers.Add($"Header {columnPos}"); + } + table.Headers = headers.ToArray(); + + var rows = new List(); + for (var rowPos = 1; rowPos <= 100000; rowPos++) + { + var row = new string[columnCount]; + for (var columnPos = 1; columnPos <= columnCount; columnPos++) + { + row[columnPos - 1] = $"Row {rowPos} -> Column {columnPos}"; + } + rows.Add(row); + } + table.Rows = rows; + + var tableString = table.ToTable(); + + Console.WriteLine(tableString); + Console.WriteLine(); + } } diff --git a/ConsoleTable.Text/Table.cs b/ConsoleTable.Text/Table.cs index 81f57cf..6592221 100644 --- a/ConsoleTable.Text/Table.cs +++ b/ConsoleTable.Text/Table.cs @@ -9,19 +9,19 @@ public class Table { private string _tableCache = null; - private bool _cachingEabled = true; + private bool _cachingEnabled = true; /// /// Enables the caching of the generated table string when the ToTable method is called. Default is true. /// Cache will be cleared on any property change or method call. /// - public bool CachingEabled + public bool CachingEnabled { - get => _cachingEabled; + get => _cachingEnabled; set { - _cachingEabled = value; + _cachingEnabled = value; - if (!_cachingEabled) + if (!_cachingEnabled) ClearCache(); } } @@ -324,7 +324,7 @@ public Table Clear() /// public string ToTable() { - if (CachingEabled && !string.IsNullOrEmpty(_tableCache)) + if (CachingEnabled && !string.IsNullOrEmpty(_tableCache)) return _tableCache; var table = new List(); @@ -388,7 +388,7 @@ public string ToTable() var generatedTable = formattedTable.ToString(); - if (CachingEabled) + if (CachingEnabled) _tableCache = generatedTable; return generatedTable; diff --git a/README.md b/README.md index b3b0075..1420407 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Output: | `Padding` | `int` | `1` | The number of spaces on each side of cell content | | `HeaderTextAlignmentRight` | `bool` | `false` | When `true`, header text is right-aligned otherwise left aligned | | `RowTextAlignmentRight` | `bool` | `false` | When `true`, row text is right-aligned otherwise left aligned | -| `CachingEabled` | `bool` | `true` | When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | +| `CachingEnabled` | `bool` | `true` | When `true`, the generated table string is cached when the ToTable method is called. Cache will be cleared on any property change or method call. | ### Methods diff --git a/Tests/ConsoleTable.Text.Tests/TableTests.cs b/Tests/ConsoleTable.Text.Tests/TableTests.cs index 4fa8748..1ad5f3e 100644 --- a/Tests/ConsoleTable.Text.Tests/TableTests.cs +++ b/Tests/ConsoleTable.Text.Tests/TableTests.cs @@ -11,7 +11,7 @@ public void PerformanceCheck(bool cacheEnabled) { var table = new Table { - CachingEabled = cacheEnabled, + CachingEnabled = cacheEnabled, HeaderTextAlignmentRight = true, RowTextAlignmentRight = false, Padding = 5 @@ -19,19 +19,19 @@ public void PerformanceCheck(bool cacheEnabled) var columnCount = 100; var headers = new List(); - for (var i = 1; i <= columnCount; i++) + for (var columnPos = 1; columnPos <= columnCount; columnPos++) { - headers.Add($"Header{i}"); + headers.Add($"Header {columnPos}"); } table.Headers = headers.ToArray(); var rows = new List(); - for (var i = 0; i < 100000; i++) + for (var rowPos = 1; rowPos <= 100000; rowPos++) { var row = new string[columnCount]; - for (var j = 1; j <= columnCount; j++) + for (var columnPos = 1; columnPos <= columnCount; columnPos++) { - row[j - 1] = $"Row {i} -> Column {j}"; + row[columnPos - 1] = $"Row {rowPos} -> Column {columnPos}"; } rows.Add(row); } @@ -600,7 +600,7 @@ public void ClearCache() { var table = new Table { - CachingEabled = true + CachingEnabled = true }; table.AddRow("1"); @@ -620,7 +620,7 @@ public void CachingEnabled(bool cachingEnabled) { var table = new Table { - CachingEabled = cachingEnabled + CachingEnabled = cachingEnabled }; table.AddRow("1");