From bd3b09cf4c25e702a2d6627c5e873372d18fa5d4 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 1 Nov 2026 17:45:59 +0100 Subject: [PATCH] UsingStaticInCSharp: net10.0, real output tests, global using static and member precedence examples --- .../UsingStaticInCSharp.Tests.csproj | 11 +- .../UsingStaticUnitTest.cs | 101 +++++++++++++----- .../UsingStaticInCSharp/Constants/Caller.cs | 2 +- .../GlobalUsingStatic/Caller.cs | 19 ++++ .../GlobalUsingStatic/GlobalUsings.cs | 1 + .../GlobalUsingStatic/Scores.cs | 5 + .../MemberPrecedence/Caller.cs | 12 +++ .../MemberPrecedence/ClassA.cs | 5 + .../NestedTypeMembers/Caller.cs | 1 + .../NestedTypeMembers/ClassA.cs | 9 +- .../NestedTypeMembers/OuterTypeCaller.cs | 11 ++ .../UsingStaticInCSharp/Program.cs | 5 +- .../UsingStaticInCSharp.csproj | 2 +- 13 files changed, 146 insertions(+), 38 deletions(-) create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Caller.cs create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/GlobalUsings.cs create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Scores.cs create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/Caller.cs create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/ClassA.cs create mode 100644 csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/OuterTypeCaller.cs diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticInCSharp.Tests.csproj b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticInCSharp.Tests.csproj index 91c441613a..3d10256151 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticInCSharp.Tests.csproj +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticInCSharp.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 enable enable @@ -9,14 +9,13 @@ - - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticUnitTest.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticUnitTest.cs index 7d553a39d1..08d40d76b9 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticUnitTest.cs +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp.Tests/UsingStaticUnitTest.cs @@ -1,59 +1,106 @@ -using Moq; - namespace UsingStaticInCSharp.Tests; + public class UsingStaticUnitTest { + private static string CaptureOutput(Action invoke) + { + var original = Console.Out; + using var writer = new StringWriter(); + Console.SetOut(writer); + try + { + invoke(); + } + finally + { + Console.SetOut(original); + } + + return writer.ToString(); + } + + [Fact] + public void GivenAStaticMethodFromClassA_WhenCalledByUsingStaticFeature_ThenItRuns() + { + var output = CaptureOutput(() => new MethodsAndProperties.Caller().Invoke()); + + Assert.Contains("MethodsAndProperties.ClassA.MethodA() called", output); + Assert.Contains("MethodsAndProperties.ClassA.MethodB() called", output); + } + + [Fact] + public void GivenAnEnum_WhenItemsAreUsedByUsingStaticFeature_ThenTheyResolve() + { + var output = CaptureOutput(() => new Enums.Caller().Invoke()); + + Assert.Contains("The enum items are User, Admin", output); + } + + [Fact] + public void GivenStaticConstants_WhenUsedByUsingStaticFeature_ThenTheyResolve() + { + var output = CaptureOutput(() => new Constants.Caller().Invoke()); + + Assert.Contains("Pending, InProgress, Completed", output); + } + + [Fact] + public void GivenANestedClass_WhenCalledByUsingStaticFeature_ThenItRuns() + { + var output = CaptureOutput(() => new NestedTypeMembers.Caller().Invoke()); + + Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodA() called", output); + Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodB() called", output); + } + [Fact] - public void GivenAStaticConstant_WhenCalledByUsingStaticFeature_ShouldBeInvoked() + public void GivenTheOuterClass_WhenImportedByUsingStatic_ThenTheNestedClassNeedsNoPrefix() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new NestedTypeMembers.OuterTypeCaller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodA() called", output); + Assert.Contains("NestedTypeMembers.ClassA.ClassB.MethodB() called", output); } [Fact] - public void GivenANestedClassFromSampleClassOne_WhenCalledByUsingStaticFeature_ShouldBeInvoked() + public void GivenAnExtensionMethodInDifferentNamespace_WhenImportedByUsingStatic_ThenItIsFound() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new ExtensionMethods.Caller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("The sum is 3", output); } [Fact] - public void GivenAStaticMethodFromClassA_WhenCalledByUsingStaticFeature_ShouldBeInvoked() + public void GivenADerivedClass_WhenItsOwnStaticMethodIsCalledByUsingStatic_ThenItRuns() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new BaseClassMembers.Caller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("BaseClassMembers.ClassB.MethodB() called", output); } [Fact] - public void GivenAAmbiguityMethodFromClassAAndClassB_WhenCalledByItsClassName_ShouldBeInvoked() + public void GivenTwoClassesWithTheSameMethod_WhenCalledByClassName_ThenBothRun() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new Ambiguity.Caller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("Ambiguity.ClassA.Method() called", output); + Assert.Contains("Ambiguity.ClassB.Method() called", output); } [Fact] - public void GivenAEnum_WhenCalledByUsingStaticFeature_ShouldBeInvoked() + public void GivenAGlobalUsingStatic_WhenMathMembersAreCalledWithoutTypeName_ThenTheyResolve() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new GlobalUsingStatic.Caller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("The hypotenuse is 5", output); + Assert.Contains("The best score is 9", output); } [Fact] - public void GivenAnExtensionMethodInDifferentNamespace_WhenCalledByUsingStaticFeature_ShouldBeInvoked() + public void GivenAMemberWithTheSameName_WhenCalledUnqualified_ThenTheEnclosingTypeWins() { - var mock = new Mock(); - mock.Object.Invoke(); + var output = CaptureOutput(() => new MemberPrecedence.Caller().Invoke()); - mock.Verify(x => x.Invoke()); + Assert.Contains("Describe() returned Caller.Describe()", output); } -} \ No newline at end of file +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Constants/Caller.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Constants/Caller.cs index 8128e0c221..76b5d3276f 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Constants/Caller.cs +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Constants/Caller.cs @@ -5,6 +5,6 @@ public class Caller { public virtual void Invoke() { - Console.WriteLine("The contants are {0}, {1}, {2}", Pending, InProgress, Completed); + Console.WriteLine("The constants are {0}, {1}, {2}", Pending, InProgress, Completed); } } diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Caller.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Caller.cs new file mode 100644 index 0000000000..3e587faec1 --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Caller.cs @@ -0,0 +1,19 @@ +using static UsingStaticInCSharp.GlobalUsingStatic.Scores; + +namespace UsingStaticInCSharp.GlobalUsingStatic; +public class Caller +{ + public virtual void Invoke() + { + var hypotenuse = Sqrt(Pow(3, 2) + Pow(4, 2)); + Console.WriteLine("The hypotenuse is {0}", hypotenuse); + + var best = Scores.Max(3, 9); + Console.WriteLine("The best score is {0}", best); + + // Error CS0121 The call is ambiguous + // between the following methods or properties: + // 'System.Math.Max(int, int)' and 'UsingStaticInCSharp.GlobalUsingStatic.Scores.Max(int, int)' + // var best = Max(3, 9); + } +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/GlobalUsings.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/GlobalUsings.cs new file mode 100644 index 0000000000..4cb9097936 --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/GlobalUsings.cs @@ -0,0 +1 @@ +global using static System.Math; diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Scores.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Scores.cs new file mode 100644 index 0000000000..d4fd99533e --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/GlobalUsingStatic/Scores.cs @@ -0,0 +1,5 @@ +namespace UsingStaticInCSharp.GlobalUsingStatic; +public static class Scores +{ + public static int Max(int first, int second) => first > second ? first : second; +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/Caller.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/Caller.cs new file mode 100644 index 0000000000..769b61bead --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/Caller.cs @@ -0,0 +1,12 @@ +using static UsingStaticInCSharp.MemberPrecedence.ClassA; + +namespace UsingStaticInCSharp.MemberPrecedence; +public class Caller +{ + public virtual void Invoke() + { + Console.WriteLine("Describe() returned {0}", Describe()); + } + + private static string Describe() => "Caller.Describe()"; +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/ClassA.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/ClassA.cs new file mode 100644 index 0000000000..f593332381 --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/MemberPrecedence/ClassA.cs @@ -0,0 +1,5 @@ +namespace UsingStaticInCSharp.MemberPrecedence; +public static class ClassA +{ + public static string Describe() => "ClassA.Describe()"; +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/Caller.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/Caller.cs index 1a516a12d4..43eb227329 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/Caller.cs +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/Caller.cs @@ -5,6 +5,7 @@ public class Caller { public virtual void Invoke() { + MethodA(); MethodB(); } } diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/ClassA.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/ClassA.cs index 4401167f46..fc921bb570 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/ClassA.cs +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/ClassA.cs @@ -1,8 +1,13 @@ namespace UsingStaticInCSharp.NestedTypeMembers; -public static class ClassA +public class ClassA { - public static class ClassB + public class ClassB { + public static void MethodA() + { + Console.WriteLine("NestedTypeMembers.ClassA.ClassB.MethodA() called"); + } + public static void MethodB() { Console.WriteLine("NestedTypeMembers.ClassA.ClassB.MethodB() called"); diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/OuterTypeCaller.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/OuterTypeCaller.cs new file mode 100644 index 0000000000..457cb48050 --- /dev/null +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/NestedTypeMembers/OuterTypeCaller.cs @@ -0,0 +1,11 @@ +using static UsingStaticInCSharp.NestedTypeMembers.ClassA; + +namespace UsingStaticInCSharp.NestedTypeMembers; +public class OuterTypeCaller +{ + public virtual void Invoke() + { + ClassB.MethodA(); + ClassB.MethodB(); + } +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Program.cs b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Program.cs index a4642aaed5..adcfdc97ae 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Program.cs +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/Program.cs @@ -7,8 +7,11 @@ static void Main(string[] args) new Enums.Caller().Invoke(); new Constants.Caller().Invoke(); new NestedTypeMembers.Caller().Invoke(); + new NestedTypeMembers.OuterTypeCaller().Invoke(); new ExtensionMethods.Caller().Invoke(); new BaseClassMembers.Caller().Invoke(); new Ambiguity.Caller().Invoke(); + new GlobalUsingStatic.Caller().Invoke(); + new MemberPrecedence.Caller().Invoke(); } -} \ No newline at end of file +} diff --git a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/UsingStaticInCSharp.csproj b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/UsingStaticInCSharp.csproj index 9ad2a07d38..ed9781c223 100644 --- a/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/UsingStaticInCSharp.csproj +++ b/csharp-basic-topics/UsingStaticInCSharp/UsingStaticInCSharp/UsingStaticInCSharp.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net10.0 enable enable