diff --git a/Directory.Build.props b/Directory.Build.props index 7be4ffb..b4b6a5f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,8 @@ 12.0 - enable + enable + annotations enable true diff --git a/Singulink.Globalization.Currency.sln b/Singulink.Globalization.Currency.sln index 55b78d9..8d16861 100644 --- a/Singulink.Globalization.Currency.sln +++ b/Singulink.Globalization.Currency.sln @@ -41,6 +41,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{764A .github\dependabot.yml = .github\dependabot.yml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Singulink.Globalization.Currency.NetStandardTests", "Tests\Singulink.Globalization.Currency.NetStandardTests\Singulink.Globalization.Currency.NetStandardTests.csproj", "{A95689C0-68A0-4457-9B2C-0357468920AE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,10 @@ Global {FE384100-51BA-42C4-B269-F0C3BCF5A6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU {FE384100-51BA-42C4-B269-F0C3BCF5A6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {FE384100-51BA-42C4-B269-F0C3BCF5A6BE}.Release|Any CPU.Build.0 = Release|Any CPU + {A95689C0-68A0-4457-9B2C-0357468920AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A95689C0-68A0-4457-9B2C-0357468920AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A95689C0-68A0-4457-9B2C-0357468920AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A95689C0-68A0-4457-9B2C-0357468920AE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -64,6 +70,7 @@ Global {FE384100-51BA-42C4-B269-F0C3BCF5A6BE} = {DBA8BA65-D53C-41A8-9534-EAB6AE159CCB} {97D96E55-E2D9-4076-8D71-BA319A703C06} = {DBA8BA65-D53C-41A8-9534-EAB6AE159CCB} {4028E49D-6194-47FA-AEA9-5B046F8013D2} = {2CD9744C-7FC1-485B-BB89-406676D56D25} + {A95689C0-68A0-4457-9B2C-0357468920AE} = {2CD9744C-7FC1-485B-BB89-406676D56D25} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06D2E21A-73BC-4E56-B817-7147C8D79C05} diff --git a/Source/Singulink.Globalization.Currency/Currency.cs b/Source/Singulink.Globalization.Currency/Currency.cs index b0b964a..6f95262 100644 --- a/Source/Singulink.Globalization.Currency/Currency.cs +++ b/Source/Singulink.Globalization.Currency/Currency.cs @@ -35,7 +35,7 @@ public class Currency : IFormattable public Money MinorUnit => new Money(new decimal(1, 0, 0, false, (byte)DecimalDigits), this); /// - /// Gets a list containing language identifers and currency names. + /// Gets a list containing language identifiers and currency names. /// public IEnumerable<(string CultureName, string Name)> LocalizedNames => _localizedNameLookup?.Select(kvp => (kvp.Key, kvp.Value)) ?? Array.Empty<(string, string)>(); @@ -54,7 +54,7 @@ public class Currency : IFormattable /// is not found. /// public Currency(string name, string currencyCode, string symbol, int decimalDigits, params (string CultureName, string Name)[] localizedNames) - : this(name, currencyCode, symbol, decimalDigits, localizedNames.Length == 0 ? null : localizedNames.AsEnumerable()) { } + : this(name, currencyCode, symbol, decimalDigits, localizedNames.Length is 0 ? null : localizedNames.AsEnumerable()) { } /// public Currency(string name, string currencyCode, string symbol, int decimalDigits, IEnumerable<(string CultureName, string Name)>? localizedNames = null) @@ -63,16 +63,16 @@ public Currency(string name, string currencyCode, string symbol, int decimalDigi name = name.Trim(); symbol = symbol.Trim(); - if (currencyCode.Length == 0) + if (currencyCode.Length is 0) throw new ArgumentException("Currency code is required.", nameof(currencyCode)); if (currencyCode.Length > 20) throw new ArgumentOutOfRangeException(nameof(currencyCode), "Currency code has a maximum length of 20 characters."); - if (name.Length == 0) + if (name.Length is 0) throw new ArgumentException("Name is required.", nameof(name)); - if (symbol.Length == 0) + if (symbol.Length is 0) throw new ArgumentException("Symbol is required.", nameof(symbol)); if (symbol.Length > 20) @@ -86,14 +86,23 @@ public Currency(string name, string currencyCode, string symbol, int decimalDigi Symbol = symbol; DecimalDigits = decimalDigits; - if (localizedNames != null) + if (localizedNames is not null) { - foreach (var (cultureName, localName) in localizedNames) + foreach (var localizedName in localizedNames) { + string cultureName = CoerceCultureName(localizedName.CultureName); + string localName = CoerceCurrencyName(localizedName.Name); + _localizedNameLookup ??= new(StringComparer.OrdinalIgnoreCase); +#if NETSTANDARD + if (_localizedNameLookup.ContainsKey(cultureName)) + throw new ArgumentException($"Duplicate culture name '{cultureName}' in localized names.", nameof(localizedNames)); - if (!_localizedNameLookup.TryAdd(CoerceCultureName(cultureName), CoerceCurrencyName(localName))) + _localizedNameLookup.Add(cultureName, localName); +#else + if (!_localizedNameLookup.TryAdd(cultureName, localName)) throw new ArgumentException($"Duplicate culture name '{cultureName}' in localized names.", nameof(localizedNames)); +#endif } } @@ -159,7 +168,7 @@ public string ToString(string? format, CultureInfo? culture = null) string name; - if (_localizedNameLookup == null) + if (_localizedNameLookup is null) { name = Name; } @@ -167,7 +176,7 @@ public string ToString(string? format, CultureInfo? culture = null) { var neutralCulture = culture.GetNeutralCulture(); - if (neutralCulture == null || !_localizedNameLookup.TryGetValue(neutralCulture.Name, out name)) + if (neutralCulture is null || !_localizedNameLookup.TryGetValue(neutralCulture.Name, out name)) name = Name; } @@ -220,9 +229,13 @@ internal static CurrencyRegistry CreateSystemRegistry() if (localizedNameLookup.TryGetValue(localizationCultureName, out string existingLocalizedName) && existingLocalizedName != localizedName) { - // This shouldn't happen, but if the data changes and it does then make this future-proof by adding the localized name to the specific - // culture instead to override the different neutral culture name that was set. + // This shouldn't happen in .NET+, but if the data changes and it does then make this future-proof by adding the localized name to the + // specific culture instead to override the different neutral culture name that was set. + + // This *does* happen on .NET Framework, so neutral culture name will be whatever specific culture name was first. +#if !NETSTANDARD Debug.Fail("Neutral localization culture name was already set to a different name."); +#endif localizedNameLookup.Add(culture.Name, localizedName); } else diff --git a/Source/Singulink.Globalization.Currency/CurrencyRegistry.cs b/Source/Singulink.Globalization.Currency/CurrencyRegistry.cs index d033285..b23abfb 100644 --- a/Source/Singulink.Globalization.Currency/CurrencyRegistry.cs +++ b/Source/Singulink.Globalization.Currency/CurrencyRegistry.cs @@ -7,7 +7,12 @@ namespace Singulink.Globalization; /// /// Represents a collection of currencies. /// -public sealed class CurrencyRegistry : ISet, IReadOnlySet +public sealed class CurrencyRegistry : ISet +#if !NETSTANDARD +#pragma warning disable SA1001 // Commas should be spaced correctly + , IReadOnlySet +#pragma warning restore SA1001 +#endif { private static CurrencyRegistry? _default; private static CurrencyRegistry? _system; @@ -25,7 +30,7 @@ public CurrencyRegistry(string name, IEnumerable currencies) { _name = name.Trim(); - if (_name.Length == 0) + if (_name.Length is 0) throw new ArgumentException("Name is required.", nameof(name)); _currencies = []; @@ -33,8 +38,19 @@ public CurrencyRegistry(string name, IEnumerable currencies) foreach (var currency in currencies) { +#if NETSTANDARD + if (_currencies.Add(currency)) + { + if (_currencyLookup.ContainsKey(currency.CurrencyCode)) + throw new ArgumentException($"Multiple currencies with currency code '{currency.CurrencyCode}'.", nameof(currencies)); + + _currencyLookup.Add(currency.CurrencyCode, currency); + } +#else if (_currencies.Add(currency) && !_currencyLookup.TryAdd(currency.CurrencyCode, currency)) throw new ArgumentException($"Multiple currencies with currency code '{currency.CurrencyCode}'.", nameof(currencies)); +#endif + } } @@ -51,7 +67,7 @@ public static CurrencyRegistry Default { get => _default ??= System; set { - if (_default != null) + if (_default is not null) throw new InvalidOperationException("Default currency registry cannot be set after it has already been set or accessed."); _default = value; diff --git a/Source/Singulink.Globalization.Currency/IImmutableMoneySet.cs b/Source/Singulink.Globalization.Currency/IImmutableMoneySet.cs index 1db09df..de08225 100644 --- a/Source/Singulink.Globalization.Currency/IImmutableMoneySet.cs +++ b/Source/Singulink.Globalization.Currency/IImmutableMoneySet.cs @@ -153,31 +153,4 @@ public interface IImmutableMoneySet : ICollection, IReadOnlyMoneySet /// Removes all zero amounts from this set and returns the resulting set. /// public IImmutableMoneySet TrimZeroAmounts(); - - #region Explicit Interface Implementations - - /// - /// Gets a value indicating whether the set is read-only. Always returns . - /// - bool ICollection.IsReadOnly => true; - - /// - /// Not supported. - /// - /// This operation is not supported. - void ICollection.Add(Money item) => throw new NotSupportedException(); - - /// - /// Not supported. - /// - /// This operation is not supported. - void ICollection.Clear() => throw new NotSupportedException(); - - /// - /// Not supported. - /// - /// This operation is not supported. - bool ICollection.Remove(Money item) => throw new NotSupportedException(); - - #endregion } \ No newline at end of file diff --git a/Source/Singulink.Globalization.Currency/ImmutableMoneySet.cs b/Source/Singulink.Globalization.Currency/ImmutableMoneySet.cs index ac1ae1f..e37d374 100644 --- a/Source/Singulink.Globalization.Currency/ImmutableMoneySet.cs +++ b/Source/Singulink.Globalization.Currency/ImmutableMoneySet.cs @@ -57,7 +57,7 @@ public static ImmutableMoneySet Create(CurrencyRegistry registry, Money value) var amountLookup = EmptyLookup; var currency = value.CurrencyOrDefault; - if (currency != null) + if (currency is not null) { EnsureCurrencyAllowed(registry, currency, nameof(value)); amountLookup = amountLookup.Add(currency, value.Amount); @@ -88,7 +88,7 @@ public static ImmutableMoneySet Create(CurrencyRegistry registry, Money value) /// public static ImmutableMoneySet Create(CurrencyRegistry registry, ReadOnlySpan values) { - if (values.Length == 0) + if (values.Length is 0) return Create(registry); var builder = EmptyLookup.ToBuilder(); @@ -97,14 +97,14 @@ public static ImmutableMoneySet Create(CurrencyRegistry registry, ReadOnlySpan values) /// public ImmutableMoneySet Clear() { - if (Count == 0) + if (Count is 0) return this; return new ImmutableMoneySet(_registry, EmptyLookup); @@ -285,7 +285,7 @@ public ImmutableMoneySet RemoveAll(IEnumerable currencies) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -302,7 +302,7 @@ public ImmutableMoneySet RemoveAll(Func predicate) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -311,7 +311,7 @@ public ImmutableMoneySet RemoveAll(Func predicate) /// public ImmutableMoneySet RoundToCurrencyDigits(MidpointRounding mode) { - if (Count == 0) + if (Count is 0) return this; ImmutableDictionary.Builder builder = null; @@ -327,7 +327,7 @@ public ImmutableMoneySet RoundToCurrencyDigits(MidpointRounding mode) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -335,7 +335,7 @@ public ImmutableMoneySet SetValue(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return this; return SetAmount(value.Amount, currency); @@ -396,7 +396,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) bool ignoreZeroAmounts; int count; - if (format != null && format.StartsWith('!')) + if (format is not null && format.Length > 0 && format[0] is '!') { format = format[1..]; ignoreZeroAmounts = true; @@ -408,7 +408,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) count = Count; } - if (count == 0) + if (count is 0) return string.Empty; var sb = new StringBuilder(count * 8); @@ -416,7 +416,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) foreach (var value in this) { - if (ignoreZeroAmounts && value.Amount == 0) + if (ignoreZeroAmounts && value.Amount is 0) continue; if (first) @@ -446,7 +446,7 @@ int GetNonZeroCount() /// public ImmutableMoneySet TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableDictionary.Builder builder = null; @@ -462,13 +462,13 @@ public ImmutableMoneySet TransformValues(Func transform) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableMoneySet TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableDictionary.Builder builder = null; @@ -489,13 +489,13 @@ public ImmutableMoneySet TransformValues(Func transform) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableMoneySet TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableDictionary.Builder builder = null; @@ -511,13 +511,13 @@ public ImmutableMoneySet TransformAmounts(Func transform) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableMoneySet TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableDictionary.Builder builder = null; @@ -538,7 +538,7 @@ public ImmutableMoneySet TransformAmounts(Func transform) } } - return builder != null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -548,14 +548,14 @@ public ImmutableMoneySet TrimZeroAmounts() foreach (var kvp in _amountLookup) { - if (kvp.Value == 0) + if (kvp.Value is 0) { builder ??= _amountLookup.ToBuilder(); builder.Remove(kvp.Key); } } - return builder == null ? this : new ImmutableMoneySet(_registry, builder.ToImmutable()); + return builder is null ? this : new ImmutableMoneySet(_registry, builder.ToImmutable()); } /// @@ -612,7 +612,7 @@ private ImmutableMoneySet AddInternal(decimal amount, Currency currency) amountLookup = _amountLookup.Add(currency, amount); } - return amountLookup == null ? this : new ImmutableMoneySet(_registry, amountLookup); + return amountLookup is null ? this : new ImmutableMoneySet(_registry, amountLookup); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -624,7 +624,7 @@ private ImmutableDictionary AddRangeInternal(IEnumerable AddRangeInternal(IEnumerable AddRangeInternal(IEnumerable SubtractRangeInternal(IEnumerable { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry) @@ -665,7 +665,7 @@ private ImmutableDictionary SubtractRangeInternal(IEnumerable if (builder?.TryGetValue(currency, out decimal existingAmount) ?? _amountLookup.TryGetValue(currency, out existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; builder ??= _amountLookup.ToBuilder(); @@ -678,7 +678,7 @@ private ImmutableDictionary SubtractRangeInternal(IEnumerable } } - return builder != null ? builder.ToImmutable() : _amountLookup; + return builder is not null ? builder.ToImmutable() : _amountLookup; } private void EnsureCurrencyAllowed(Currency currency, string paramName) => EnsureCurrencyAllowed(_registry, currency, paramName); @@ -707,10 +707,15 @@ static void Throw(CurrencyRegistry registry, Currency currency, string paramName #endif /// - bool IReadOnlyMoneySet.IsSorted => false; + IReadOnlyCollection IReadOnlyMoneySet.Currencies => Currencies; /// - IReadOnlyCollection IReadOnlyMoneySet.Currencies => Currencies; + bool IReadOnlyMoneySet.IsSorted => false; + + /// + /// Gets a value indicating whether the set is read-only. Always returns . + /// + bool ICollection.IsReadOnly => true; /// IImmutableMoneySet IImmutableMoneySet.Add(Money value) => Add(value); @@ -798,6 +803,28 @@ void ICollection.CopyTo(Money[] array, int arrayIndex) #endregion + #region Not Supported + + /// + /// Not supported. + /// + /// This operation is not supported. + void ICollection.Add(Money item) => throw new NotSupportedException(); + + /// + /// Not supported. + /// + /// This operation is not supported. + void ICollection.Clear() => throw new NotSupportedException(); + + /// + /// Not supported. + /// + /// This operation is not supported. + bool ICollection.Remove(Money item) => throw new NotSupportedException(); + + #endregion + /// /// Enumerates the elements of a . /// diff --git a/Source/Singulink.Globalization.Currency/ImmutableSortedMoneySet.cs b/Source/Singulink.Globalization.Currency/ImmutableSortedMoneySet.cs index aedfe92..fb7de4e 100644 --- a/Source/Singulink.Globalization.Currency/ImmutableSortedMoneySet.cs +++ b/Source/Singulink.Globalization.Currency/ImmutableSortedMoneySet.cs @@ -57,7 +57,7 @@ public static ImmutableSortedMoneySet Create(CurrencyRegistry registry, Money va var amountLookup = EmptyLookup; var currency = value.CurrencyOrDefault; - if (currency != null) + if (currency is not null) { EnsureCurrencyAllowed(registry, currency, nameof(value)); amountLookup = amountLookup.Add(currency, value.Amount); @@ -88,7 +88,7 @@ public static ImmutableSortedMoneySet Create(CurrencyRegistry registry, Money va /// public static ImmutableSortedMoneySet Create(CurrencyRegistry registry, ReadOnlySpan values) { - if (values.Length == 0) + if (values.Length is 0) return Create(registry); var builder = EmptyLookup.ToBuilder(); @@ -97,14 +97,14 @@ public static ImmutableSortedMoneySet Create(CurrencyRegistry registry, ReadOnly { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; EnsureCurrencyAllowed(registry, currency, nameof(values)); if (builder.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; builder[currency] = existingAmount + value.Amount; @@ -182,7 +182,7 @@ public ImmutableSortedMoneySet Add(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return this; EnsureCurrencyAllowed(currency, nameof(value)); @@ -214,7 +214,7 @@ public ImmutableSortedMoneySet AddRange(IEnumerable values) /// public ImmutableSortedMoneySet Clear() { - if (Count == 0) + if (Count is 0) return this; return new ImmutableSortedMoneySet(_registry, EmptyLookup); @@ -285,7 +285,7 @@ public ImmutableSortedMoneySet RemoveAll(IEnumerable currencies) } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -302,7 +302,7 @@ public ImmutableSortedMoneySet RemoveAll(Func predicate) } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -311,7 +311,7 @@ public ImmutableSortedMoneySet RemoveAll(Func predicate) /// public ImmutableSortedMoneySet RoundToCurrencyDigits(MidpointRounding mode) { - if (Count == 0) + if (Count is 0) return this; ImmutableSortedDictionary.Builder builder = null; @@ -327,7 +327,7 @@ public ImmutableSortedMoneySet RoundToCurrencyDigits(MidpointRounding mode) } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -335,7 +335,7 @@ public ImmutableSortedMoneySet SetValue(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return this; return SetAmount(value.Amount, currency); @@ -396,7 +396,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) bool ignoreZeroAmounts; int count; - if (format != null && format.StartsWith('!')) + if (format is not null && format.Length > 0 && format[0] is '!') { format = format[1..]; ignoreZeroAmounts = true; @@ -408,7 +408,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) count = Count; } - if (count == 0) + if (count is 0) return string.Empty; var sb = new StringBuilder(count * 8); @@ -416,7 +416,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) foreach (var value in this) { - if (ignoreZeroAmounts && value.Amount == 0) + if (ignoreZeroAmounts && value.Amount is 0) continue; if (first) @@ -446,7 +446,7 @@ int GetNonZeroCount() /// public ImmutableSortedMoneySet TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableSortedDictionary.Builder builder = null; @@ -462,13 +462,13 @@ public ImmutableSortedMoneySet TransformValues(Func transform) } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableSortedMoneySet TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableSortedDictionary.Builder builder = null; @@ -489,13 +489,13 @@ public ImmutableSortedMoneySet TransformValues(Func transform) } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableSortedMoneySet TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableSortedDictionary.Builder builder = null; @@ -511,13 +511,13 @@ public ImmutableSortedMoneySet TransformAmounts(Func transform } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// public ImmutableSortedMoneySet TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return this; ImmutableSortedDictionary.Builder builder = null; @@ -538,7 +538,7 @@ public ImmutableSortedMoneySet TransformAmounts(Func transfor } } - return builder != null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; + return builder is not null ? new ImmutableSortedMoneySet(_registry, builder.ToImmutable()) : this; } /// @@ -548,14 +548,14 @@ public ImmutableSortedMoneySet TrimZeroAmounts() foreach (var kvp in _amountLookup) { - if (kvp.Value == 0) + if (kvp.Value is 0) { builder ??= _amountLookup.ToBuilder(); builder.Remove(kvp.Key); } } - return builder == null ? this : new ImmutableSortedMoneySet(_registry, builder.ToImmutable()); + return builder is null ? this : new ImmutableSortedMoneySet(_registry, builder.ToImmutable()); } /// @@ -612,7 +612,7 @@ private ImmutableSortedMoneySet AddInternal(decimal amount, Currency currency) amountLookup = _amountLookup.Add(currency, amount); } - return amountLookup == null ? this : new ImmutableSortedMoneySet(_registry, amountLookup); + return amountLookup is null ? this : new ImmutableSortedMoneySet(_registry, amountLookup); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -624,7 +624,7 @@ private ImmutableSortedDictionary AddRangeInternal(IEnumerabl { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry) @@ -632,7 +632,7 @@ private ImmutableSortedDictionary AddRangeInternal(IEnumerabl if (builder?.TryGetValue(currency, out decimal existingAmount) ?? _amountLookup.TryGetValue(currency, out existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; builder ??= _amountLookup.ToBuilder(); @@ -645,7 +645,7 @@ private ImmutableSortedDictionary AddRangeInternal(IEnumerabl } } - return builder != null ? builder.ToImmutable() : _amountLookup; + return builder is not null ? builder.ToImmutable() : _amountLookup; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -657,7 +657,7 @@ private ImmutableSortedDictionary SubtractRangeInternal(IEnum { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry) @@ -665,7 +665,7 @@ private ImmutableSortedDictionary SubtractRangeInternal(IEnum if (builder?.TryGetValue(currency, out decimal existingAmount) ?? _amountLookup.TryGetValue(currency, out existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; builder ??= _amountLookup.ToBuilder(); @@ -678,7 +678,7 @@ private ImmutableSortedDictionary SubtractRangeInternal(IEnum } } - return builder != null ? builder.ToImmutable() : _amountLookup; + return builder is not null ? builder.ToImmutable() : _amountLookup; } private void EnsureCurrencyAllowed(Currency currency, string paramName) => EnsureCurrencyAllowed(_registry, currency, paramName); @@ -707,10 +707,15 @@ static void Throw(CurrencyRegistry registry, Currency currency, string paramName #endif /// - bool IReadOnlyMoneySet.IsSorted => true; + IReadOnlyCollection IReadOnlyMoneySet.Currencies => Currencies; /// - IReadOnlyCollection IReadOnlyMoneySet.Currencies => Currencies; + bool IReadOnlyMoneySet.IsSorted => true; + + /// + /// Gets a value indicating whether the set is read-only. Always returns . + /// + bool ICollection.IsReadOnly => true; /// IImmutableMoneySet IImmutableMoneySet.Add(Money value) => Add(value); @@ -798,6 +803,28 @@ void ICollection.CopyTo(Money[] array, int arrayIndex) #endregion + #region Not Supported + + /// + /// Not supported. + /// + /// This operation is not supported. + void ICollection.Add(Money item) => throw new NotSupportedException(); + + /// + /// Not supported. + /// + /// This operation is not supported. + void ICollection.Clear() => throw new NotSupportedException(); + + /// + /// Not supported. + /// + /// This operation is not supported. + bool ICollection.Remove(Money item) => throw new NotSupportedException(); + + #endregion + /// /// Enumerates the elements of a . /// diff --git a/Source/Singulink.Globalization.Currency/Money.ToString.cs b/Source/Singulink.Globalization.Currency/Money.ToString.cs index 5fa5678..197988f 100644 --- a/Source/Singulink.Globalization.Currency/Money.ToString.cs +++ b/Source/Singulink.Globalization.Currency/Money.ToString.cs @@ -20,8 +20,10 @@ private static readonly ImmutableArray NegativeInternationalPatterns private static readonly ImmutableArray NegativeReverseInternationalPatterns = ["(n) $", "-n $", "-n $", "n- $", "(n) $", "-n $", "n- $", "n- $", "-n $", "-n $", "n- $", "n- $", "-n $", "n- $", "(n) $", "(n) $"]; - private static readonly ConditionalWeakTable _regionInfoLookup = []; - private static readonly ConditionalWeakTable _absNumberFormatInfoLookup = []; +#pragma warning disable IDE0028 // Simplify collection initialization (not supported on NS2) + private static readonly ConditionalWeakTable _regionInfoLookup = new(); + private static readonly ConditionalWeakTable _absNumberFormatInfoLookup = new(); +#pragma warning restore IDE0028 /// /// Returns a culture-dependent international string representation of this value's currency and amount. @@ -68,24 +70,34 @@ private static readonly ImmutableArray NegativeReverseInternationalPatte /// Format specifier was invalid. public string ToString(string? format, IFormatProvider? formatProvider = null) { +#if NETSTANDARD + ParseFormat(format, out char symbolFormat, out char decimalsFormat, out int decimalsFormatNumber, out char resultNumberFormatType); +#else Span resultNumberFormat = stackalloc char[3]; ParseFormat(format, out char symbolFormat, out char decimalsFormat, out int decimalsFormatNumber, out resultNumberFormat[0]); +#endif CultureInfo culture = GetCultureAndSetFormatProvider(ref formatProvider); RegionInfo? region = null; decimal absFormatAmount = GetFormatAmountAndDecimalPlaces(Math.Abs(_amount), _currency, decimalsFormat, decimalsFormatNumber, out int formatDecimalPlaces); + var absNumberFormatInfo = GetAbsNumberFormatInfo(formatProvider); + +#if NETSTANDARD + string resultNumberFormat = $"{resultNumberFormatType}{formatDecimalPlaces}"; + string number = absFormatAmount.ToString(resultNumberFormat, absNumberFormatInfo); +#else formatDecimalPlaces.TryFormat(resultNumberFormat[1..], out int formatDecimalPlacesLength, null, CultureInfo.InvariantCulture); resultNumberFormat = resultNumberFormat[..(1 + formatDecimalPlacesLength)]; // Enough capacity for whole number (29) + group separators (14) + decimal separator (1) + decimals (29) Span number = stackalloc char[73]; - var absNumberFormatInfo = GetAbsNumberFormatInfo(formatProvider); if (!absFormatAmount.TryFormat(number, out int numberLength, resultNumberFormat, absNumberFormatInfo)) throw new UnreachableException($"Unexpected number formatting failure (resultNumberFormat: '{resultNumberFormat}')."); number = number[..numberLength]; +#endif if (_currency is null) return number.ToString(); // number must be zero with no currency so we can stop formatting here @@ -141,7 +153,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) if (currencySymbol == absNumberFormatInfo.CurrencyDecimalSeparator) currencySymbol = string.Empty; +#if NETSTANDARD + return ApplyPattern(number.AsSpan(), pattern, currencySymbol, absNumberFormatInfo.NegativeSign, placeCurrencySymbolAsDecimalSeparator); +#else return ApplyPattern(number, pattern, currencySymbol, absNumberFormatInfo.NegativeSign, placeCurrencySymbolAsDecimalSeparator); +#endif } private static string ApplyPattern(ReadOnlySpan number, string pattern, string currencySymbol, string negativeSign, bool placeCurrencySymbolAsDecimalSeparator) @@ -162,12 +178,12 @@ private static string ApplyPattern(ReadOnlySpan number, string pattern, st if (decimalIndex == -1) { Append(ref remaining, number); - Append(ref remaining, currencySymbol); + Append(ref remaining, currencySymbol.AsSpan()); } else { Append(ref remaining, number[..decimalIndex]); - Append(ref remaining, currencySymbol); + Append(ref remaining, currencySymbol.AsSpan()); Append(ref remaining, number[(decimalIndex + 1)..]); } } @@ -180,11 +196,11 @@ private static string ApplyPattern(ReadOnlySpan number, string pattern, st case '$': if (!placeCurrencySymbolAsDecimalSeparator && currencySymbol != Constants.ZeroWidthSpace) - Append(ref remaining, currencySymbol); + Append(ref remaining, currencySymbol.AsSpan()); break; case '-': - Append(ref remaining, negativeSign); + Append(ref remaining, negativeSign.AsSpan()); break; case ' ': @@ -217,7 +233,7 @@ private static CultureInfo GetCultureAndSetFormatProvider(ref IFormatProvider? f { CultureInfo culture; - if (formatProvider == null) + if (formatProvider is null) formatProvider = culture = CultureInfo.CurrentCulture; else culture = formatProvider as CultureInfo ?? CultureInfo.CurrentCulture; @@ -242,7 +258,7 @@ private static decimal GetFormatAmountAndDecimalPlaces(decimal amount, Currency? if (decimalsFormat == default || decimalsFormat == '*') { int amountDecimalDigits = amount.GetDecimalDigits(); - formatDecimalPlaces = decimalsFormat == '*' && amountDecimalDigits == 0 ? 0 : Math.Max(amountDecimalDigits, currency?.DecimalDigits ?? 0); + formatDecimalPlaces = decimalsFormat == '*' && amountDecimalDigits is 0 ? 0 : Math.Max(amountDecimalDigits, currency?.DecimalDigits ?? 0); } else { @@ -265,10 +281,14 @@ private static RegionInfo GetRegionForCulture(CultureInfo culture) try { region = new RegionInfo(culture.Name); +#if NETSTANDARD + _regionInfoLookup.Add(culture, region); +#endif } catch { } - +#if !NETSTANDARD _regionInfoLookup.AddOrUpdate(culture, region); +#endif } return region ?? RegionInfo.CurrentRegion; @@ -332,7 +352,11 @@ void Next() var decimalsFormatNumberSpan = format.AsSpan()[currentIndex..]; if (decimalsFormatNumberSpan.Length > 2 || +#if NETSTANDARD + !int.TryParse(decimalsFormatNumberSpan.ToString(), NumberStyles.None, CultureInfo.InvariantCulture, out decimalsFormatNumber) || +#else !int.TryParse(decimalsFormatNumberSpan, NumberStyles.None, CultureInfo.InvariantCulture, out decimalsFormatNumber) || +#endif decimalsFormatNumber is < 0 or > 28) { Throw(); diff --git a/Source/Singulink.Globalization.Currency/Money.cs b/Source/Singulink.Globalization.Currency/Money.cs index 88ac80c..97a83ca 100644 --- a/Source/Singulink.Globalization.Currency/Money.cs +++ b/Source/Singulink.Globalization.Currency/Money.cs @@ -45,7 +45,7 @@ public Money(decimal amount, Currency currency) /// Creates a new value with the specified amount and currency code. Allows creating default money values by passing 0 for /// the amount and for the currency code. Currency code must be provided if the amount is non-zero. /// - public static Money CreateDefaultable(decimal amount, string? currencyCode) => CreateDefaultable(amount, currencyCode == null ? null : Currency.Get(currencyCode)); + public static Money CreateDefaultable(decimal amount, string? currencyCode) => CreateDefaultable(amount, currencyCode is null ? null : Currency.Get(currencyCode)); /// /// Creates a new value with the specified amount and currency. Allows creating default money values by passing 0 for @@ -53,7 +53,7 @@ public Money(decimal amount, Currency currency) /// public static Money CreateDefaultable(decimal amount, Currency? currency) { - if (currency == null) + if (currency is null) { if (amount != 0) ThrowCurrencyRequiredForNonZeroAmount(); @@ -99,7 +99,7 @@ public Currency Currency /// [MemberNotNullWhen(false, nameof(CurrencyOrDefault))] [MemberNotNullWhen(false, nameof(_currency))] - public bool IsDefault => _currency == null; + public bool IsDefault => _currency is null; #region Operators @@ -194,13 +194,13 @@ public Currency Currency /// public Money RoundToCurrencyDigits(MidpointRounding mode) { - return _currency == null ? this : new Money(Math.Round(_amount, _currency.DecimalDigits, mode), Currency); + return _currency is null ? this : new Money(Math.Round(_amount, _currency.DecimalDigits, mode), Currency); } /// /// Returns if this value's is 0, otherwise returns this value. /// - public Money ToDefaultIfZero() => _amount == 0 ? default : this; + public Money ToDefaultIfZero() => _amount is 0 ? default : this; #region Equality and Comparison diff --git a/Source/Singulink.Globalization.Currency/MoneySet.cs b/Source/Singulink.Globalization.Currency/MoneySet.cs index d2fec59..aabf57d 100644 --- a/Source/Singulink.Globalization.Currency/MoneySet.cs +++ b/Source/Singulink.Globalization.Currency/MoneySet.cs @@ -72,14 +72,14 @@ public MoneySet(CurrencyRegistry registry, ReadOnlySpan values) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; EnsureCurrencyAllowed(currency, nameof(values)); if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount + value.Amount; @@ -135,7 +135,7 @@ public void Add(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return; EnsureCurrencyAllowed(currency, nameof(value)); @@ -232,7 +232,7 @@ public int RemoveAll(IEnumerable currencies) count++; } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(currencies)); return count; @@ -252,7 +252,7 @@ public int RemoveAll(Func predicate) } } - if (currenciesToRemove != null) + if (currenciesToRemove is not null) { foreach (var currency in currenciesToRemove) { @@ -271,7 +271,7 @@ public int RemoveAll(Func predicate) /// public void RoundToCurrencyDigits(MidpointRounding mode) { - if (Count == 0) + if (Count is 0) return; List> updatedEntries = null; @@ -287,7 +287,7 @@ public void RoundToCurrencyDigits(MidpointRounding mode) } } - if (updatedEntries == null) + if (updatedEntries is null) return; foreach (var entry in updatedEntries) @@ -301,7 +301,7 @@ public void SetValue(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return; SetAmount(value.Amount, currency); @@ -358,7 +358,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) bool ignoreZeroAmounts; int count; - if (format != null && format.StartsWith('!')) + if (format is not null && format.Length > 0 && format[0] is '!') { format = format[1..]; ignoreZeroAmounts = true; @@ -370,7 +370,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) count = Count; } - if (count == 0) + if (count is 0) return string.Empty; var sb = new StringBuilder(count * 8); @@ -378,7 +378,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) foreach (var value in this) { - if (ignoreZeroAmounts && value.Amount == 0) + if (ignoreZeroAmounts && value.Amount is 0) continue; if (first) @@ -408,7 +408,7 @@ int GetNonZeroCount() /// public void TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -427,7 +427,7 @@ public void TransformValues(Func transform) /// public void TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -450,7 +450,7 @@ public void TransformValues(Func transform) /// public void TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -470,7 +470,7 @@ public void TransformAmounts(Func transform) /// public void TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -497,14 +497,14 @@ public int TrimZeroAmounts() foreach (var kvp in _amountLookup) { - if (kvp.Value == 0) + if (kvp.Value is 0) { currenciesToRemove ??= []; currenciesToRemove.Add(kvp.Key); } } - if (currenciesToRemove != null) + if (currenciesToRemove is not null) { foreach (var currency in currenciesToRemove) { @@ -573,7 +573,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry && !_registry.Contains(currency)) @@ -585,7 +585,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount + value.Amount; @@ -596,7 +596,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn } } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(values)); } @@ -608,7 +608,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry && !_registry.Contains(currency)) @@ -620,7 +620,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount - value.Amount; @@ -631,7 +631,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc } } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(values)); } diff --git a/Source/Singulink.Globalization.Currency/Singulink.Globalization.Currency.csproj b/Source/Singulink.Globalization.Currency/Singulink.Globalization.Currency.csproj index 2713b56..6288463 100644 --- a/Source/Singulink.Globalization.Currency/Singulink.Globalization.Currency.csproj +++ b/Source/Singulink.Globalization.Currency/Singulink.Globalization.Currency.csproj @@ -1,6 +1,6 @@  - net6.0;net7.0 + netstandard2.0;net6.0;net7.0 Singulink.Globalization true @@ -12,11 +12,13 @@ https://github.com/Singulink/Singulink.Globalization.Currency + + + + + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Source/Singulink.Globalization.Currency/SortedMoneySet.cs b/Source/Singulink.Globalization.Currency/SortedMoneySet.cs index 8bbac45..816bada 100644 --- a/Source/Singulink.Globalization.Currency/SortedMoneySet.cs +++ b/Source/Singulink.Globalization.Currency/SortedMoneySet.cs @@ -72,14 +72,14 @@ public SortedMoneySet(CurrencyRegistry registry, ReadOnlySpan values) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; EnsureCurrencyAllowed(currency, nameof(values)); if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount + value.Amount; @@ -135,7 +135,7 @@ public void Add(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return; EnsureCurrencyAllowed(currency, nameof(value)); @@ -232,7 +232,7 @@ public int RemoveAll(IEnumerable currencies) count++; } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(currencies)); return count; @@ -252,7 +252,7 @@ public int RemoveAll(Func predicate) } } - if (currenciesToRemove != null) + if (currenciesToRemove is not null) { foreach (var currency in currenciesToRemove) { @@ -271,7 +271,7 @@ public int RemoveAll(Func predicate) /// public void RoundToCurrencyDigits(MidpointRounding mode) { - if (Count == 0) + if (Count is 0) return; List> updatedEntries = null; @@ -287,7 +287,7 @@ public void RoundToCurrencyDigits(MidpointRounding mode) } } - if (updatedEntries == null) + if (updatedEntries is null) return; foreach (var entry in updatedEntries) @@ -301,7 +301,7 @@ public void SetValue(Money value) { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) return; SetAmount(value.Amount, currency); @@ -363,7 +363,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) bool ignoreZeroAmounts; int count; - if (format != null && format.StartsWith('!')) + if (format is not null && format.Length > 0 && format[0] is '!') { format = format[1..]; ignoreZeroAmounts = true; @@ -375,7 +375,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) count = Count; } - if (count == 0) + if (count is 0) return string.Empty; var sb = new StringBuilder(count * 8); @@ -383,7 +383,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) foreach (var value in this) { - if (ignoreZeroAmounts && value.Amount == 0) + if (ignoreZeroAmounts && value.Amount is 0) continue; if (first) @@ -413,7 +413,7 @@ int GetNonZeroCount() /// public void TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -432,7 +432,7 @@ public void TransformValues(Func transform) /// public void TransformValues(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -455,7 +455,7 @@ public void TransformValues(Func transform) /// public void TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -475,7 +475,7 @@ public void TransformAmounts(Func transform) /// public void TransformAmounts(Func transform) { - if (Count == 0) + if (Count is 0) return; // TODO: Optimize if no values change. @@ -502,14 +502,14 @@ public int TrimZeroAmounts() foreach (var kvp in _amountLookup) { - if (kvp.Value == 0) + if (kvp.Value is 0) { currenciesToRemove ??= []; currenciesToRemove.Add(kvp.Key); } } - if (currenciesToRemove != null) + if (currenciesToRemove is not null) { foreach (var currency in currenciesToRemove) { @@ -578,7 +578,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry && !_registry.Contains(currency)) @@ -590,7 +590,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount + value.Amount; @@ -601,7 +601,7 @@ private void AddRangeInternal(IEnumerable values, bool ensureCurrenciesIn } } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(values)); } @@ -613,7 +613,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc { var currency = value.CurrencyOrDefault; - if (currency == null) + if (currency is null) continue; if (ensureCurrenciesInRegistry && !_registry.Contains(currency)) @@ -625,7 +625,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc if (_amountLookup.TryGetValue(currency, out decimal existingAmount)) { - if (value.Amount == 0) + if (value.Amount is 0) continue; _amountLookup[currency] = existingAmount - value.Amount; @@ -636,7 +636,7 @@ private void SubtractRangeInternal(IEnumerable values, bool ensureCurrenc } } - if (disallowedCurrencies != null) + if (disallowedCurrencies is not null) ThrowCurrenciesDisallowed(disallowedCurrencies, nameof(values)); } diff --git a/Source/Singulink.Globalization.Currency/Utilities/CultureInfoExtensions.cs b/Source/Singulink.Globalization.Currency/Utilities/CultureInfoExtensions.cs index 03bfdf5..12abe04 100644 --- a/Source/Singulink.Globalization.Currency/Utilities/CultureInfoExtensions.cs +++ b/Source/Singulink.Globalization.Currency/Utilities/CultureInfoExtensions.cs @@ -8,7 +8,7 @@ internal static class CultureInfoExtensions /// public static CultureInfo? GetNeutralCulture(this CultureInfo culture) { - if (culture == null) + if (culture is null) throw new ArgumentNullException(nameof(culture)); while (true) @@ -18,7 +18,7 @@ internal static class CultureInfoExtensions culture = culture.Parent; - if (culture == null) + if (culture is null) return null; } } diff --git a/Tests/Singulink.Globalization.Currency.NetStandardTests/Singulink.Globalization.Currency.NetStandardTests.csproj b/Tests/Singulink.Globalization.Currency.NetStandardTests/Singulink.Globalization.Currency.NetStandardTests.csproj new file mode 100644 index 0000000..8267505 --- /dev/null +++ b/Tests/Singulink.Globalization.Currency.NetStandardTests/Singulink.Globalization.Currency.NetStandardTests.csproj @@ -0,0 +1,21 @@ + + + net481 + enable + + false + true + + + + + + + + + + + + + + diff --git a/Tests/Singulink.Globalization.Currency.NetStandardTests/Usings.cs b/Tests/Singulink.Globalization.Currency.NetStandardTests/Usings.cs new file mode 100644 index 0000000..6d97b50 --- /dev/null +++ b/Tests/Singulink.Globalization.Currency.NetStandardTests/Usings.cs @@ -0,0 +1,4 @@ +global using System.Collections.Immutable; +global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using PrefixClassName.MsTest; +global using Shouldly; \ No newline at end of file