From e96f6ec579d1b76f7bbbee4cb227e61bff10ed75 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 18 Oct 2026 00:04:27 +0200 Subject: [PATCH] Readonly Modifier in C#: retarget net10.0, Playlist, Counter/Tally trap, Book init property, three tests Both projects net7.0 to net10.0. Microsoft.NET.Test.Sdk 18.11.0, xunit 2.9.3, xunit.runner.visualstudio 4.0.1, coverlet.collector 10.1.0. New Playlist (a readonly List field that still accepts items; the reassignment in Reset() stays commented out as a compiler error), Counter (a mutable struct with a readonly Describe() method), Tally (a readonly Counter field whose Increment() calls run on a defensive copy, so Total stays 0) and Book (required init-only Title). Program.cs prints each one. Three new tests: the readonly list changes, the readonly struct field total stays 0, and a Counter variable increments to 2. Existing files and tests unchanged. --- .../ReadOnlyModifierInCSharp/Book.cs | 7 ++++ .../ReadOnlyModifierInCSharp/Counter.cs | 17 ++++++++++ .../ReadOnlyModifierInCSharp/Playlist.cs | 19 +++++++++++ .../ReadOnlyModifierInCSharp/Program.cs | 22 ++++++++++++- .../ReadOnlyModifierInCSharp.csproj | 2 +- .../ReadOnlyModifierInCSharp/Tally.cs | 14 ++++++++ .../ReadOnlyTests/ReadOnlyTests.cs | 32 ++++++++++++++++++- .../ReadOnlyTests/ReadOnlyTests.csproj | 10 +++--- 8 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Book.cs create mode 100644 csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Counter.cs create mode 100644 csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Playlist.cs create mode 100644 csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Tally.cs diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Book.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Book.cs new file mode 100644 index 0000000000..820e655fc1 --- /dev/null +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Book.cs @@ -0,0 +1,7 @@ +namespace ReadOnlyModifierInCSharp +{ + public class Book + { + public required string Title { get; init; } + } +} diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Counter.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Counter.cs new file mode 100644 index 0000000000..a169914300 --- /dev/null +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Counter.cs @@ -0,0 +1,17 @@ +namespace ReadOnlyModifierInCSharp +{ + public struct Counter + { + public int Value { get; private set; } + + public void Increment() + { + Value++; + } + + public readonly string Describe() + { + return $"Counted {Value} times"; + } + } +} diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Playlist.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Playlist.cs new file mode 100644 index 0000000000..4fe0eae17b --- /dev/null +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Playlist.cs @@ -0,0 +1,19 @@ +namespace ReadOnlyModifierInCSharp +{ + public class Playlist + { + private readonly List _songs = new(); + + public int Count => _songs.Count; + + public void Add(string song) + { + _songs.Add(song); + } + + public void Reset() + { + //_songs = new List(); //Throws Compiler Error + } + } +} diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Program.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Program.cs index f1843e1800..b37261d19e 100644 --- a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Program.cs +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Program.cs @@ -18,4 +18,24 @@ //person.Name = "Emily"; //Throws compiler error person.ChangeName("Emily"); -Console.WriteLine($"Changed Name: {person.Name}"); \ No newline at end of file +Console.WriteLine($"Changed Name: {person.Name}"); + +var playlist = new Playlist(); +playlist.Add("Bohemian Rhapsody"); +playlist.Add("Hotel California"); +Console.WriteLine($"Songs: {playlist.Count}"); + +var tally = new Tally(); +tally.Count(); +tally.Count(); +Console.WriteLine($"Total: {tally.Total}"); + +var counter = new Counter(); +counter.Increment(); +counter.Increment(); +Console.WriteLine(counter.Describe()); + +var book = new Book { Title = "Dune" }; +Console.WriteLine($"Title: {book.Title}"); + +//book.Title = "Emma"; //Throws compiler error diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp.csproj b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp.csproj index f02677bf64..dfb40caafc 100644 --- a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp.csproj +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net10.0 enable enable diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Tally.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Tally.cs new file mode 100644 index 0000000000..436708900b --- /dev/null +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyModifierInCSharp/Tally.cs @@ -0,0 +1,14 @@ +namespace ReadOnlyModifierInCSharp +{ + public class Tally + { + private readonly Counter _counter; + + public int Total => _counter.Value; + + public void Count() + { + _counter.Increment(); + } + } +} diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.cs b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.cs index bdb7c4da7d..977555c6df 100644 --- a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.cs +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.cs @@ -20,4 +20,34 @@ public void GivenPerson_WhenCallingChangeName_ThenNameChanged() Assert.Equal(expectedName, person.Name); } -} \ No newline at end of file + + [Fact] + public void GivenReadonlyListField_WhenAddingSongs_ThenListChanges() + { + var playlist = new Playlist(); + playlist.Add("Bohemian Rhapsody"); + playlist.Add("Hotel California"); + + Assert.Equal(2, playlist.Count); + } + + [Fact] + public void GivenReadonlyStructField_WhenCountingTwice_ThenTotalStaysZero() + { + var tally = new Tally(); + tally.Count(); + tally.Count(); + + Assert.Equal(0, tally.Total); + } + + [Fact] + public void GivenCounterVariable_WhenIncrementingTwice_ThenValueIsTwo() + { + var counter = new Counter(); + counter.Increment(); + counter.Increment(); + + Assert.Equal("Counted 2 times", counter.Describe()); + } +} diff --git a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.csproj b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.csproj index 2c5f1dc0d0..0c8f91bf24 100644 --- a/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.csproj +++ b/csharp-intermediate-topics/ReadOnlyModifierInCSharp/ReadOnlyTests/ReadOnlyTests.csproj @@ -1,7 +1,7 @@ - net7.0 + net10.0 enable enable @@ -10,13 +10,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all