From b92fc03cc05d28eca8a6ee6fea547802b0b20c28 Mon Sep 17 00:00:00 2001 From: Andrew Kalinin Date: Fri, 23 May 2025 15:42:36 +0300 Subject: [PATCH] add: task --- NullElements/.editorconfig | 4 + .../NullElements.Tests.csproj | 39 +++++++ .../NullElements.Tests/NullElementsTests.cs | 108 ++++++++++++++++++ NullElements/NullElements.Tests/stylecop.json | 15 +++ NullElements/NullElements.sln | 36 ++++++ NullElements/NullElements/Counter.cs | 45 ++++++++ NullElements/NullElements/ICheckNulls.cs | 20 ++++ NullElements/NullElements/IntNullChecker.cs | 19 +++ NullElements/NullElements/MyList.cs | 59 ++++++++++ NullElements/NullElements/NullElements.csproj | 25 ++++ NullElements/NullElements/Program.cs | 13 +++ .../NullElements/StringNullChecker.cs | 19 +++ NullElements/NullElements/stylecop.json | 15 +++ 13 files changed, 417 insertions(+) create mode 100644 NullElements/.editorconfig create mode 100644 NullElements/NullElements.Tests/NullElements.Tests.csproj create mode 100644 NullElements/NullElements.Tests/NullElementsTests.cs create mode 100644 NullElements/NullElements.Tests/stylecop.json create mode 100644 NullElements/NullElements.sln create mode 100644 NullElements/NullElements/Counter.cs create mode 100644 NullElements/NullElements/ICheckNulls.cs create mode 100644 NullElements/NullElements/IntNullChecker.cs create mode 100644 NullElements/NullElements/MyList.cs create mode 100644 NullElements/NullElements/NullElements.csproj create mode 100644 NullElements/NullElements/Program.cs create mode 100644 NullElements/NullElements/StringNullChecker.cs create mode 100644 NullElements/NullElements/stylecop.json diff --git a/NullElements/.editorconfig b/NullElements/.editorconfig new file mode 100644 index 0000000..bc75ec6 --- /dev/null +++ b/NullElements/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# SA1600: Elements should be documented +dotnet_diagnostic.SA1600.severity = none diff --git a/NullElements/NullElements.Tests/NullElements.Tests.csproj b/NullElements/NullElements.Tests/NullElements.Tests.csproj new file mode 100644 index 0000000..ce411f2 --- /dev/null +++ b/NullElements/NullElements.Tests/NullElements.Tests.csproj @@ -0,0 +1,39 @@ + + + + net9.0 + latest + enable + enable + false + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/NullElements/NullElements.Tests/NullElementsTests.cs b/NullElements/NullElements.Tests/NullElementsTests.cs new file mode 100644 index 0000000..3594869 --- /dev/null +++ b/NullElements/NullElements.Tests/NullElementsTests.cs @@ -0,0 +1,108 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +namespace NullElements.Tests +{ + public class NullElementsTests + { + [Test] + public void Add_NumberToEmptyList_ShouldIncreaseCountByOne() + { + var testList = new MyList(); + testList.Add(5); + + Assert.That(testList.Count, Is.EqualTo(1)); + } + + [Test] + public void Add_Overflow_ShouldDoubleInternalArraySize() + { + var testList = new MyList(); + var initialCapacity = 10; + for (int i = 0; i < initialCapacity + 1; ++i) + { + testList.Add(i); + } + + Assert.That(testList.Count, Is.EqualTo(11)); + } + + [Test] + public void GetEnumerator_ValidData_ShouldIterateInCorrectOrder() + { + var testList = new MyList(); + testList.Add(1); + testList.Add(2); + + var result = new System.Collections.Generic.List(); + foreach (var item in testList) + { + result.Add(item); + } + + Assert.That(result, Is.EqualTo(new[] { 1, 2 })); + } + + [Test] + public void GetEnumerator_WhenListIsEmpty_ShouldNotIterate() + { + var testList = new MyList(); + + var iterations = 0; + foreach (var item in testList) + { + iterations++; + } + + Assert.That(iterations, Is.EqualTo(0)); + } + + [Test] + public void CountNulls_String_ShouldReturnCorrectCount() + { + var testList = new MyList(); + testList.Add("hello"); + testList.Add(null); + testList.Add(string.Empty); + testList.Add("world"); + + var result = Counter.CountNulls(testList, new StringNullChecker()); + + Assert.That(result, Is.EqualTo(2)); + } + + [Test] + public void CountNulls_Int_ShouldReturnCorrectCountZeros() + { + var testList = new MyList(); + testList.Add(0); + testList.Add(1); + testList.Add(0); + + var result = Counter.CountNulls(testList, new IntNullChecker()); + + Assert.That(result, Is.EqualTo(2)); + } + + [Test] + public void CountNulls_WhenIntListIsEmpty_ShouldReturnZero() + { + var testList = new MyList(); + + var result = Counter.CountNulls(testList, new IntNullChecker()); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public void CountNulls_WhenStringListIsEmpty_ShouldReturnZero() + { + var testList = new MyList(); + + var result = Counter.CountNulls(testList, new StringNullChecker()); + + Assert.That(result, Is.EqualTo(0)); + } + } +} diff --git a/NullElements/NullElements.Tests/stylecop.json b/NullElements/NullElements.Tests/stylecop.json new file mode 100644 index 0000000..577bdb3 --- /dev/null +++ b/NullElements/NullElements.Tests/stylecop.json @@ -0,0 +1,15 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Kalinin Andrew", + "copyrightText": "Copyright (c) {companyName}. All rights reserved." + } + } +} diff --git a/NullElements/NullElements.sln b/NullElements/NullElements.sln new file mode 100644 index 0000000..285f4bb --- /dev/null +++ b/NullElements/NullElements.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35806.99 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NullElements", "NullElements\NullElements.csproj", "{2BA0FF1E-3004-4D5F-A36F-9E7122EE2145}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NullElements.Tests", "NullElements.Tests\NullElements.Tests.csproj", "{1AE28732-923A-4DDE-BE64-28751F09CC28}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2BA0FF1E-3004-4D5F-A36F-9E7122EE2145}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BA0FF1E-3004-4D5F-A36F-9E7122EE2145}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BA0FF1E-3004-4D5F-A36F-9E7122EE2145}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BA0FF1E-3004-4D5F-A36F-9E7122EE2145}.Release|Any CPU.Build.0 = Release|Any CPU + {1AE28732-923A-4DDE-BE64-28751F09CC28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AE28732-923A-4DDE-BE64-28751F09CC28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AE28732-923A-4DDE-BE64-28751F09CC28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AE28732-923A-4DDE-BE64-28751F09CC28}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {979D0980-DB24-4BC7-909D-644F6A87E14F} + EndGlobalSection +EndGlobal diff --git a/NullElements/NullElements/Counter.cs b/NullElements/NullElements/Counter.cs new file mode 100644 index 0000000..3a86309 --- /dev/null +++ b/NullElements/NullElements/Counter.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +namespace NullElements +{ + /// + /// Provides utility methods for working with collections. + /// + public static class Counter + { + /// + /// Counts elements that match null-equivalent conditions. + /// + /// The type of elements in the list. + /// The collection to inspect. + /// The null-equivalence checker implementation. + /// The number of null-equivalent elements. + /// Thrown when list or checker is null.(MyList list, ICheckNulls checker) + { + if (list == null) + { + throw new ArgumentNullException(nameof(list)); + } + + if (checker == null) + { + throw new ArgumentNullException(nameof(checker)); + } + + int count = 0; + + foreach (var item in list) + { + if (checker.IsNull(item)) + { + count++; + } + } + + return count; + } + } +} diff --git a/NullElements/NullElements/ICheckNulls.cs b/NullElements/NullElements/ICheckNulls.cs new file mode 100644 index 0000000..9588f50 --- /dev/null +++ b/NullElements/NullElements/ICheckNulls.cs @@ -0,0 +1,20 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +namespace NullElements +{ + /// + /// Interface for checking if elements meet null-equivalent conditions. + /// + /// The type of elements to check. + public interface ICheckNulls + { + /// + /// Determines if an item should be considered null-equivalent. + /// + /// The item to check. + /// True if the item is considered null-equivalent, otherwise False. + bool IsNull(T item); + } +} diff --git a/NullElements/NullElements/IntNullChecker.cs b/NullElements/NullElements/IntNullChecker.cs new file mode 100644 index 0000000..566d87c --- /dev/null +++ b/NullElements/NullElements/IntNullChecker.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +namespace NullElements +{ + /// + /// Null-equivalence checker for integer values. + /// + public class IntNullChecker : ICheckNulls + { + /// + /// Determines if an integer is zero. + /// + /// The integer to check. + /// True if the value is zero, otherwise False. + public bool IsNull(int item) => item == 0; + } +} diff --git a/NullElements/NullElements/MyList.cs b/NullElements/NullElements/MyList.cs new file mode 100644 index 0000000..7e90b29 --- /dev/null +++ b/NullElements/NullElements/MyList.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +using System.Collections; + +/// +/// Custom generic list implementation with dynamic resizing. +/// +/// The type of elements in the list. +public class MyList : IEnumerable +{ + private T[] items; + + private int count; + + /// + /// Initializes a new instance of the class. + /// + public MyList() + { + this.items = new T[4]; + this.count = 0; + } + + public int Count => this.count; + + /// + /// Adds an item to the end of the list. + /// + /// The item to add. + public void Add(T item) + { + if (this.count == this.items.Length) + { + Array.Resize(ref this.items, this.items.Length == 0 ? 10 : this.items.Length * 2); + } + + this.items[this.count] = item; + this.count++; + } + + /// + /// Returns an enumerator that iterates through the collection. + /// + /// An enumerator for the list. + public IEnumerator GetEnumerator() + { + for (int i = 0; i < this.count; ++i) + { + yield return this.items[i]; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } +} diff --git a/NullElements/NullElements/NullElements.csproj b/NullElements/NullElements/NullElements.csproj new file mode 100644 index 0000000..091f9ba --- /dev/null +++ b/NullElements/NullElements/NullElements.csproj @@ -0,0 +1,25 @@ + + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/NullElements/NullElements/Program.cs b/NullElements/NullElements/Program.cs new file mode 100644 index 0000000..1350381 --- /dev/null +++ b/NullElements/NullElements/Program.cs @@ -0,0 +1,13 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +using NullElements; + +var intList = new MyList(); +intList.Add(0); +intList.Add(0); +intList.Add(0); +intList.Add(0); + +Console.WriteLine(Counter.CountNulls(intList, new IntNullChecker())); diff --git a/NullElements/NullElements/StringNullChecker.cs b/NullElements/NullElements/StringNullChecker.cs new file mode 100644 index 0000000..7f87015 --- /dev/null +++ b/NullElements/NullElements/StringNullChecker.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Kalinin Andrew. All rights reserved. +// + +namespace NullElements +{ + /// + /// Null-equivalence checker for string values + /// + public class StringNullChecker : ICheckNulls + { + /// + /// Determines if a string is null or empty. + /// + /// The string to check. + /// True for null or empty strings, otherwise False. + public bool IsNull(string item) => item == null || item == string.Empty; + } +} diff --git a/NullElements/NullElements/stylecop.json b/NullElements/NullElements/stylecop.json new file mode 100644 index 0000000..577bdb3 --- /dev/null +++ b/NullElements/NullElements/stylecop.json @@ -0,0 +1,15 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Kalinin Andrew", + "copyrightText": "Copyright (c) {companyName}. All rights reserved." + } + } +}