From f35dbd5ce3102ab3368f2fad981cff2cf6f94d18 Mon Sep 17 00:00:00 2001 From: Andrew Koryavchenko Date: Sun, 20 Jun 2021 22:00:22 +0300 Subject: [PATCH 1/3] Index/Range targeting. Cleanup. --- Build/Props/CodeJam.Default.props | 4 +- .../PlatformHelper.cs | 0 CodeJam.Main/Algorithms/Algorithms.Swap.cs | 8 +- CodeJam.Main/Assertions/CodeExceptions.cs | 14 ++ CodeJam.Main/CodeJam.Main.csproj.DotSettings | 2 +- CodeJam.Main/ExceptionExtensions.cs | 6 +- .../[Boundaries]/RangeBoundaryFrom`1.cs | 2 +- CodeJam.Main/Strings/StringExtensions.cs | 6 +- CodeJam.Main/Structures/Option/Option`1.cs | 2 +- CodeJam.Main/Targeting/Index.cs | 152 ++++++++++++++++++ CodeJam.Main/Targeting/Range.cs | 136 ++++++++++++++++ CodeJam.Main/Threading/ParallelExtensions.cs | 7 +- CodeJam.sln.DotSettings | 1 + 13 files changed, 316 insertions(+), 24 deletions(-) rename {CodeJam.Main/Targeting => CodeJam.Main.Tests}/PlatformHelper.cs (100%) create mode 100644 CodeJam.Main/Targeting/Index.cs create mode 100644 CodeJam.Main/Targeting/Range.cs diff --git a/Build/Props/CodeJam.Default.props b/Build/Props/CodeJam.Default.props index b49fee11d..848b8f8ca 100644 --- a/Build/Props/CodeJam.Default.props +++ b/Build/Props/CodeJam.Default.props @@ -10,9 +10,7 @@ 9.0 enable - latest - true - AllEnabledByDefault + False 4.0.0.0 4.0.0-beta2 diff --git a/CodeJam.Main/Targeting/PlatformHelper.cs b/CodeJam.Main.Tests/PlatformHelper.cs similarity index 100% rename from CodeJam.Main/Targeting/PlatformHelper.cs rename to CodeJam.Main.Tests/PlatformHelper.cs diff --git a/CodeJam.Main/Algorithms/Algorithms.Swap.cs b/CodeJam.Main/Algorithms/Algorithms.Swap.cs index 48e9c414e..a03a04a45 100644 --- a/CodeJam.Main/Algorithms/Algorithms.Swap.cs +++ b/CodeJam.Main/Algorithms/Algorithms.Swap.cs @@ -13,11 +13,7 @@ public static partial class Algorithms /// Type of values /// First value to swap. /// Second value to swap. - public static void Swap(ref T value1, ref T value2) - { - var temp = value1; - value1 = value2; - value2 = temp; - } + public static void Swap(ref T value1, ref T value2) => + (value1, value2) = (value2, value1); } } \ No newline at end of file diff --git a/CodeJam.Main/Assertions/CodeExceptions.cs b/CodeJam.Main/Assertions/CodeExceptions.cs index c79af1257..d2711276a 100644 --- a/CodeJam.Main/Assertions/CodeExceptions.cs +++ b/CodeJam.Main/Assertions/CodeExceptions.cs @@ -154,6 +154,20 @@ public static ArgumentOutOfRangeException ArgumentOutOfRange( .LogToCodeTraceSourceBeforeThrow(); } + /// Creates for an argument that must be positive. + /// Name of the argument. + /// Initialized instance of . + [DebuggerHidden, MustUseReturnValue] + public static ArgumentOutOfRangeException ArgumentNegative([InvokerParameterName] string argumentName) + { + BreakIfAttached(); + return + new ArgumentOutOfRangeException( + argumentName, + $"The value of {argumentName} must be positive") + .LogToCodeTraceSourceBeforeThrow(); + } + /// Creates . /// Name of the argument. /// The value. diff --git a/CodeJam.Main/CodeJam.Main.csproj.DotSettings b/CodeJam.Main/CodeJam.Main.csproj.DotSettings index 4600c9ec1..786523c4d 100644 --- a/CodeJam.Main/CodeJam.Main.csproj.DotSettings +++ b/CodeJam.Main/CodeJam.Main.csproj.DotSettings @@ -19,7 +19,7 @@ False True True - False + True True True True diff --git a/CodeJam.Main/ExceptionExtensions.cs b/CodeJam.Main/ExceptionExtensions.cs index f3ebf43c9..7a65aa94c 100644 --- a/CodeJam.Main/ExceptionExtensions.cs +++ b/CodeJam.Main/ExceptionExtensions.cs @@ -75,8 +75,7 @@ public static void ToDiagnosticString( switch (ex) { - case FileNotFoundException notFoundException: - var fex = notFoundException; + case FileNotFoundException fex: writer.WriteLine($"File Name: {fex.FileName}"); @@ -155,8 +154,7 @@ private static async Task ToDiagnosticStringImplAsync( switch (ex) { - case FileNotFoundException notFoundException: - var fex = notFoundException; + case FileNotFoundException fex: await writer.WriteLineAsync($"File Name: {fex.FileName}").ConfigureAwait(false); diff --git a/CodeJam.Main/Ranges/[Boundaries]/RangeBoundaryFrom`1.cs b/CodeJam.Main/Ranges/[Boundaries]/RangeBoundaryFrom`1.cs index da3ff5464..f9258834d 100644 --- a/CodeJam.Main/Ranges/[Boundaries]/RangeBoundaryFrom`1.cs +++ b/CodeJam.Main/Ranges/[Boundaries]/RangeBoundaryFrom`1.cs @@ -69,7 +69,7 @@ public partial struct RangeBoundaryFrom : public static RangeBoundaryFrom AdjustAndCreate(T? value, RangeBoundaryFromKind boundaryKind) { DebugCode.AssertArgument( - boundaryKind == RangeBoundaryFromKind.Inclusive || boundaryKind == RangeBoundaryFromKind.Exclusive, + boundaryKind is RangeBoundaryFromKind.Inclusive or RangeBoundaryFromKind.Exclusive, nameof(boundaryKind), "The boundary kind should be be either Inclusive or Exclusive"); diff --git a/CodeJam.Main/Strings/StringExtensions.cs b/CodeJam.Main/Strings/StringExtensions.cs index 1c963b811..1139018a2 100644 --- a/CodeJam.Main/Strings/StringExtensions.cs +++ b/CodeJam.Main/Strings/StringExtensions.cs @@ -101,7 +101,7 @@ public static string Substring(this string str, StringOrigin origin, int length) return origin switch { - StringOrigin.Begin => str.Substring(0, length), + StringOrigin.Begin => str[..length], StringOrigin.End => str.Substring(strLen - length, length), _ => throw CodeExceptions.Argument(nameof(origin), $"Invalid {nameof(StringOrigin)} value.") }; @@ -175,7 +175,7 @@ public static string TrimPrefix( return str; var actPrefix = str.Prefix(prefixLen); - return !comparer.Equals(prefix, actPrefix) ? str : str.Substring(prefixLen); + return !comparer.Equals(prefix, actPrefix) ? str : str[prefixLen..]; } /// @@ -203,7 +203,7 @@ public static string TrimSuffix(this string str, string? suffix, IEqualityCompar return str; var actPrefix = str.Suffix(suffixLen); - return !comparer.Equals(suffix, actPrefix) ? str : str.Substring(0, strLen - suffixLen); + return !comparer.Equals(suffix, actPrefix) ? str : str[..(strLen - suffixLen)]; } /// diff --git a/CodeJam.Main/Structures/Option/Option`1.cs b/CodeJam.Main/Structures/Option/Option`1.cs index f4e26f5a7..7f3171d06 100644 --- a/CodeJam.Main/Structures/Option/Option`1.cs +++ b/CodeJam.Main/Structures/Option/Option`1.cs @@ -100,7 +100,7 @@ public bool Equals(Option? other) var otherSome = other as Some; - if (!(this is Some)) + if (this is not Some) return otherSome is null; if (otherSome is null) diff --git a/CodeJam.Main/Targeting/Index.cs b/CodeJam.Main/Targeting/Index.cs new file mode 100644 index 000000000..f2fd4c850 --- /dev/null +++ b/CodeJam.Main/Targeting/Index.cs @@ -0,0 +1,152 @@ +#if TARGETS_NET || LESSTHAN_NETSTANDARD21 +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +using CodeJam; + +using JetBrains.Annotations; + +using MethodImplOptionsEx = CodeJam.Targeting.MethodImplOptionsEx; + +// ReSharper disable once CheckNamespace +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + [PublicAPI] + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw CodeExceptions.ArgumentNegative(nameof(value)); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) => _value = value; + + /// Create an Index pointing at first element. + public static Index Start => new(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw CodeExceptions.ArgumentNegative(nameof(value)); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw CodeExceptions.ArgumentNegative(nameof(value)); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value => _value < 0 ? ~_value : _value; + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] + public int GetOffset(int length) + { + var offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals([NotNullWhen(true)] object? obj) => obj is Index index && _value == index._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return ToStringFromEnd(); + + return ((uint)Value).ToString(); + } + + private string ToStringFromEnd() + { +#if (!NETSTANDARD2_0 && !TARGETS_NET) + Span span = stackalloc char[11]; // 1 for ^ and 10 for longest possible uint value + // ReSharper disable once RedundantAssignment + bool formatted = ((uint)Value).TryFormat(span[1..], out int charsWritten); + Debug.Assert(formatted); + span[0] = '^'; + return new string(span[..(charsWritten + 1)]); +#else + return '^' + Value.ToString(); +#endif + } + } +} +#endif \ No newline at end of file diff --git a/CodeJam.Main/Targeting/Range.cs b/CodeJam.Main/Targeting/Range.cs new file mode 100644 index 000000000..04669d19a --- /dev/null +++ b/CodeJam.Main/Targeting/Range.cs @@ -0,0 +1,136 @@ +#if TARGETS_NET || LESSTHAN_NETSTANDARD21 +// BASEDON: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Range.cs + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + +using CodeJam; + +using JetBrains.Annotations; + +using MethodImplOptionsEx = CodeJam.Targeting.MethodImplOptionsEx; + +namespace System +{ + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + [PublicAPI] + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() => HashCode.Combine(Start.GetHashCode(), End.GetHashCode()); + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { +#if (!NETSTANDARD2_0 && !TARGETS_NET) + Span span = stackalloc char[2 + (2 * 11)]; // 2 for "..", then for each index 1 for '^' and 10 for longest possible uint + int pos = 0; + + if (Start.IsFromEnd) + { + span[0] = '^'; + pos = 1; + } + // ReSharper disable once RedundantAssignment + bool formatted = ((uint)Start.Value).TryFormat(span[pos..], out int charsWritten); + Debug.Assert(formatted); + pos += charsWritten; + + span[pos++] = '.'; + span[pos++] = '.'; + + if (End.IsFromEnd) + { + span[pos++] = '^'; + } + // ReSharper disable once RedundantAssignment + formatted = ((uint)End.Value).TryFormat(span[pos..], out charsWritten); + Debug.Assert(formatted); + pos += charsWritten; + + return new string(span[..pos]); +#else + return $"{Start}..{End}"; +#endif + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new(Index.Start, Index.End); + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + var startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + var endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw CodeExceptions.ArgumentOutOfRange(nameof(length), length, start, end); + } + + return (start, end - start); + } + } +} +#endif \ No newline at end of file diff --git a/CodeJam.Main/Threading/ParallelExtensions.cs b/CodeJam.Main/Threading/ParallelExtensions.cs index 236364680..78358e465 100644 --- a/CodeJam.Main/Threading/ParallelExtensions.cs +++ b/CodeJam.Main/Threading/ParallelExtensions.cs @@ -120,13 +120,10 @@ public static void RunInParallel( string processName = "ParallelProcess") { Code.NotNull(source, nameof(source)); - + using var queue = new ParallelQueue(parallelCount, processName + '_'); foreach (var action in source) - { - var data = action; - queue.EnqueueItem(data); - } + queue.EnqueueItem(action); queue.WaitAll(); } diff --git a/CodeJam.sln.DotSettings b/CodeJam.sln.DotSettings index 03ecbfadb..d8ef8bfe2 100644 --- a/CodeJam.sln.DotSettings +++ b/CodeJam.sln.DotSettings @@ -25,6 +25,7 @@ Code.NotNull($EXPR$, $NAME$); SUGGESTION SUGGESTION SUGGESTION + DO_NOT_SHOW HINT DO_NOT_SHOW SUGGESTION From a2fb834011a3f52a728d462fdb94fbfa03cdac56 Mon Sep 17 00:00:00 2001 From: NN Date: Mon, 12 Jul 2021 20:48:42 +0300 Subject: [PATCH 2/3] Use Theraot 3.2.7 --- CodeJam.Main/CodeJam.Main.csproj | 14 +-- CodeJam.Main/Targeting/Index.cs | 152 ------------------------------- CodeJam.Main/Targeting/Range.cs | 136 --------------------------- 3 files changed, 7 insertions(+), 295 deletions(-) delete mode 100644 CodeJam.Main/Targeting/Index.cs delete mode 100644 CodeJam.Main/Targeting/Range.cs diff --git a/CodeJam.Main/CodeJam.Main.csproj b/CodeJam.Main/CodeJam.Main.csproj index fe932c3d6..be64517a4 100644 --- a/CodeJam.Main/CodeJam.Main.csproj +++ b/CodeJam.Main/CodeJam.Main.csproj @@ -39,34 +39,34 @@ - + - + - + - + - + - + - + diff --git a/CodeJam.Main/Targeting/Index.cs b/CodeJam.Main/Targeting/Index.cs deleted file mode 100644 index f2fd4c850..000000000 --- a/CodeJam.Main/Targeting/Index.cs +++ /dev/null @@ -1,152 +0,0 @@ -#if TARGETS_NET || LESSTHAN_NETSTANDARD21 -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -using CodeJam; - -using JetBrains.Annotations; - -using MethodImplOptionsEx = CodeJam.Targeting.MethodImplOptionsEx; - -// ReSharper disable once CheckNamespace -namespace System -{ - /// Represent a type can be used to index a collection either from the start or the end. - /// - /// Index is used by the C# compiler to support the new index syntax - /// - /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; - /// int lastElement = someArray[^1]; // lastElement = 5 - /// - /// - [PublicAPI] - internal readonly struct Index : IEquatable - { - private readonly int _value; - - /// Construct an Index using a value and indicating if the index is from the start or from the end. - /// The index value. it has to be zero or positive number. - /// Indicating if the index is from the start or from the end. - /// - /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. - /// - [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] - public Index(int value, bool fromEnd = false) - { - if (value < 0) - { - throw CodeExceptions.ArgumentNegative(nameof(value)); - } - - if (fromEnd) - _value = ~value; - else - _value = value; - } - - // The following private constructors mainly created for perf reason to avoid the checks - private Index(int value) => _value = value; - - /// Create an Index pointing at first element. - public static Index Start => new(0); - - /// Create an Index pointing at beyond last element. - public static Index End => new(~0); - - /// Create an Index from the start at the position indicated by the value. - /// The index value from the start. - [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] - public static Index FromStart(int value) - { - if (value < 0) - { - throw CodeExceptions.ArgumentNegative(nameof(value)); - } - - return new Index(value); - } - - /// Create an Index from the end at the position indicated by the value. - /// The index value from the end. - [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] - public static Index FromEnd(int value) - { - if (value < 0) - { - throw CodeExceptions.ArgumentNegative(nameof(value)); - } - - return new Index(~value); - } - - /// Returns the index value. - public int Value => _value < 0 ? ~_value : _value; - - /// Indicates whether the index is from the start or the end. - public bool IsFromEnd => _value < 0; - - /// Calculate the offset from the start using the giving collection length. - /// The length of the collection that the Index will be used with. length has to be a positive value - /// - /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. - /// we don't validate either the returned offset is greater than the input length. - /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and - /// then used to index a collection will get out of range exception which will be same affect as the validation. - /// - [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] - public int GetOffset(int length) - { - var offset = _value; - if (IsFromEnd) - { - // offset = length - (~value) - // offset = length + (~(~value) + 1) - // offset = length + value + 1 - - offset += length + 1; - } - return offset; - } - - /// Indicates whether the current Index object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals([NotNullWhen(true)] object? obj) => obj is Index index && _value == index._value; - - /// Indicates whether the current Index object is equal to another Index object. - /// An object to compare with this object - public bool Equals(Index other) => _value == other._value; - - /// Returns the hash code for this instance. - public override int GetHashCode() => _value; - - /// Converts integer number to an Index. - public static implicit operator Index(int value) => FromStart(value); - - /// Converts the value of the current Index object to its equivalent string representation. - public override string ToString() - { - if (IsFromEnd) - return ToStringFromEnd(); - - return ((uint)Value).ToString(); - } - - private string ToStringFromEnd() - { -#if (!NETSTANDARD2_0 && !TARGETS_NET) - Span span = stackalloc char[11]; // 1 for ^ and 10 for longest possible uint value - // ReSharper disable once RedundantAssignment - bool formatted = ((uint)Value).TryFormat(span[1..], out int charsWritten); - Debug.Assert(formatted); - span[0] = '^'; - return new string(span[..(charsWritten + 1)]); -#else - return '^' + Value.ToString(); -#endif - } - } -} -#endif \ No newline at end of file diff --git a/CodeJam.Main/Targeting/Range.cs b/CodeJam.Main/Targeting/Range.cs deleted file mode 100644 index 04669d19a..000000000 --- a/CodeJam.Main/Targeting/Range.cs +++ /dev/null @@ -1,136 +0,0 @@ -#if TARGETS_NET || LESSTHAN_NETSTANDARD21 -// BASEDON: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Range.cs - -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; - -using CodeJam; - -using JetBrains.Annotations; - -using MethodImplOptionsEx = CodeJam.Targeting.MethodImplOptionsEx; - -namespace System -{ - /// Represent a range has start and end indexes. - /// - /// Range is used by the C# compiler to support the range syntax. - /// - /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; - /// int[] subArray1 = someArray[0..2]; // { 1, 2 } - /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } - /// - /// - [PublicAPI] - internal readonly struct Range : IEquatable - { - /// Represent the inclusive start index of the Range. - public Index Start { get; } - - /// Represent the exclusive end index of the Range. - public Index End { get; } - - /// Construct a Range object using the start and end indexes. - /// Represent the inclusive start index of the range. - /// Represent the exclusive end index of the range. - public Range(Index start, Index end) - { - Start = start; - End = end; - } - - /// Indicates whether the current Range object is equal to another object of the same type. - /// An object to compare with this object - public override bool Equals([NotNullWhen(true)] object? obj) => - obj is Range r && - r.Start.Equals(Start) && - r.End.Equals(End); - - /// Indicates whether the current Range object is equal to another Range object. - /// An object to compare with this object - public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); - - /// Returns the hash code for this instance. - public override int GetHashCode() => HashCode.Combine(Start.GetHashCode(), End.GetHashCode()); - - /// Converts the value of the current Range object to its equivalent string representation. - public override string ToString() - { -#if (!NETSTANDARD2_0 && !TARGETS_NET) - Span span = stackalloc char[2 + (2 * 11)]; // 2 for "..", then for each index 1 for '^' and 10 for longest possible uint - int pos = 0; - - if (Start.IsFromEnd) - { - span[0] = '^'; - pos = 1; - } - // ReSharper disable once RedundantAssignment - bool formatted = ((uint)Start.Value).TryFormat(span[pos..], out int charsWritten); - Debug.Assert(formatted); - pos += charsWritten; - - span[pos++] = '.'; - span[pos++] = '.'; - - if (End.IsFromEnd) - { - span[pos++] = '^'; - } - // ReSharper disable once RedundantAssignment - formatted = ((uint)End.Value).TryFormat(span[pos..], out charsWritten); - Debug.Assert(formatted); - pos += charsWritten; - - return new string(span[..pos]); -#else - return $"{Start}..{End}"; -#endif - } - - /// Create a Range object starting from start index to the end of the collection. - public static Range StartAt(Index start) => new(start, Index.End); - - /// Create a Range object starting from first element in the collection to the end Index. - public static Range EndAt(Index end) => new(Index.Start, end); - - /// Create a Range object starting from first element to the end. - public static Range All => new(Index.Start, Index.End); - - /// Calculate the start offset and length of range object using a collection length. - /// The length of the collection that the range will be used with. length has to be a positive value. - /// - /// For performance reason, we don't validate the input length parameter against negative values. - /// It is expected Range will be used with collections which always have non negative length/count. - /// We validate the range is inside the length scope though. - /// - [MethodImpl(MethodImplOptionsEx.AggressiveInlining)] - public (int Offset, int Length) GetOffsetAndLength(int length) - { - int start; - var startIndex = Start; - if (startIndex.IsFromEnd) - start = length - startIndex.Value; - else - start = startIndex.Value; - - int end; - var endIndex = End; - if (endIndex.IsFromEnd) - end = length - endIndex.Value; - else - end = endIndex.Value; - - if ((uint)end > (uint)length || (uint)start > (uint)end) - { - throw CodeExceptions.ArgumentOutOfRange(nameof(length), length, start, end); - } - - return (start, end - start); - } - } -} -#endif \ No newline at end of file From 0df4ab95955d5c4666803be36703de5660e6a10f Mon Sep 17 00:00:00 2001 From: NN Date: Tue, 13 Jul 2021 04:55:27 +0300 Subject: [PATCH 3/3] Use Theraot 3.2.8 --- CodeJam.Main/CodeJam.Main.csproj | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/CodeJam.Main/CodeJam.Main.csproj b/CodeJam.Main/CodeJam.Main.csproj index be64517a4..4e0234c6d 100644 --- a/CodeJam.Main/CodeJam.Main.csproj +++ b/CodeJam.Main/CodeJam.Main.csproj @@ -39,34 +39,31 @@ - + - - + - - + - - + - + - + - +