public void EnumerationTest() { const int count = 1000; Dictionary <string, int> dictionary = Enumerable.Range(0, count).ToDictionary(i => i.ToString(CultureInfo.InvariantCulture)); var strDict = new StringKeyedDictionary <int>(dictionary); new PerformanceTest <int> { TestName = "Indexer access test", Iterations = count } .AddCase(() => { int sum = 0; foreach (KeyValuePair <string, int> item in dictionary) { sum += item.Value; } return(sum); }, "Dictionary foreach") .AddCase(() => dictionary.Sum(item => item.Value), "Dictionary LINQ") .AddCase(() => { int sum = 0; foreach (KeyValuePair <string, int> item in strDict) { sum += item.Value; } return(sum); }, "StringKeyedDictionary foreach") .AddCase(() => strDict.Sum(item => item.Value), "StringKeyedDictionary LINQ") .DoTest() .DumpResults(Console.Out); }
public void SerializationTest(StringComparison comparison) { var dict = new StringKeyedDictionary <int>(StringSegmentComparer.FromComparison(comparison)) { { "alpha", 1 }, { "beta", 2 }, { "gamma", 3 }, { "delta", 4 }, { "epsilon", 5 } }; // By BinarySerializationFormatter StringKeyedDictionary <int> clone = dict.DeepClone(); Assert.AreNotSame(dict, clone); Assert.AreEqual(dict.Count, clone.Count); CollectionAssert.AreEqual(dict, clone); // By BinaryFormatter var formatter = new BinaryFormatter(); using var ms = new MemoryStream(); formatter.Serialize(ms, dict); ms.Position = 0; clone = (StringKeyedDictionary <int>)formatter.Deserialize(ms); CollectionAssert.AreEqual(dict, clone); }
public void KeysValuesTest() { var dict = new StringKeyedDictionary <int> { { "alpha", 1 }, { "beta", 2 }, { "gamma", 3 }, { "delta", 4 }, { "epsilon", 5 } }; ICollection <string> keys = dict.Keys; Assert.AreEqual(dict.Count, keys.Count); CollectionAssert.AreEqual(dict.Select(c => c.Key), dict.Keys); ICollection <int> values = dict.Values; Assert.AreEqual(dict.Count, values.Count); CollectionAssert.AreEqual(dict.Select(c => c.Value), dict.Values); Assert.IsTrue(dict.Remove("beta")); Assert.AreEqual(dict.Count, keys.Count); Assert.AreEqual(dict.Count, values.Count); }
public void ShouldMapBetweenSameComplexTypeDictionaryImplementations() { var source = new StringKeyedDictionary <Address> { ["One"] = new Address { Line1 = "1.1", Line2 = "1.2" }, ["Two"] = new Address { Line1 = "2.1", Line2 = "2.2" }, ["Three"] = default(Address), }; var result = Mapper.Map(source).ToANew <StringKeyedDictionary <Address> >(); result.Count.ShouldBe(3); result.ShouldContainKey("One"); result["One"].Line1.ShouldBe("1.1"); result["One"].Line2.ShouldBe("1.2"); result.ShouldContainKey("Two"); result["Two"].Line1.ShouldBe("2.1"); result["Two"].Line2.ShouldBe("2.2"); result.ShouldContainKey("Three"); result["Three"].ShouldBeNull(); }
public void ShouldMergeAComplexTypeArrayFromUntypedDictionaryImplementationEntries() { var source = new StringKeyedDictionary <object> { ["Value[0]"] = new CustomerViewModel { Name = "Mr Pants" }, ["Value[1]"] = new PersonViewModel { Name = "Ms Blouse" } }; var target = new PublicProperty <PersonViewModel[]> { Value = new PersonViewModel[] { new CustomerViewModel { Name = "Sir Trousers", Discount = 0.99 } } }; var originalValue1 = target.Value.First(); var result = Mapper.Map(source).OnTo(target); result.Value.Length.ShouldBe(3); result.Value.First().ShouldBe(originalValue1); result.Value.Second().Name.ShouldBe("Mr Pants"); result.Value.Third().Name.ShouldBe("Ms Blouse"); }
public void ShouldMapBetweenDictionaryImplementations() { var source = new StringKeyedDictionary <Product> { ["One"] = new Product { ProductId = "One!", Price = 9.99 }, ["Two"] = new Product { ProductId = "Two!", Price = 10.00 } }; var target = new StringKeyedDictionary <ProductDto> { ["One"] = new ProductDto { ProductId = "One!", Price = 99.99m } }; var result = Mapper.Map(source).OnTo(target); result.Count.ShouldBe(2); result["One"].ProductId.ShouldBe("One!"); result["One"].Price.ShouldBe(9.99m); result["Two"].ProductId.ShouldBe("Two!"); result["Two"].Price.ShouldBe(10.00m); }
public void ShouldMapToAnIntMemberFromADictionaryImplementationTypedEntry() { var source = new StringKeyedDictionary <long> { ["Value"] = 999 }; var result = Mapper.Map(source).ToANew <PublicField <long> >(); result.ShouldNotBeNull(); result.Value.ShouldBe(999L); }
public void ShouldOverwriteFromASimpleTypeDictionaryImplementation() { var source = new StringKeyedDictionary <string> { ["Value"] = "LaLaLa!" }; var target = new PublicField <string> { Value = "DumDeeDum!" }; var result = Mapper.Map(source).Over(target); result.Value.ShouldBe("LaLaLa!"); }
public void PopulateTest() { const int count = 1_000_000; var dict = new Dictionary <string, int>(count); var strDict = new StringKeyedDictionary <int>(count); new IteratorPerformanceTest { TestName = "Populate test", Iterations = count } .AddCase(i => dict[i.ToString(CultureInfo.InvariantCulture)] = i, "Dictionary") .AddCase(i => strDict[i.ToString(CultureInfo.InvariantCulture)] = i, "StringKeyedDictionary") .DoTest() .DumpResults(Console.Out); }
public void ShouldMapBetweenSameDeclaredSimpleTypeIDictionaries() { IDictionary <string, string> source = new StringKeyedDictionary <string> { ["Hello"] = "Bonjour", ["Yes"] = "Oui" }; var result = Mapper.Map(source).ToANew <IDictionary <string, string> >(); result.Count.ShouldBe(2); result.ShouldContainKey("Hello"); result["Hello"].ShouldBe("Bonjour"); result.ShouldContainKey("Yes"); result["Yes"].ShouldBe("Oui"); }
public void ShouldOverwriteASimpleTypeArrayToADictionaryImplementation() { var source = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() }; var target = new StringKeyedDictionary <string> { ["[0]"] = source.First().ToString(), ["[1]"] = source.Third().ToString(), ["[4]"] = Guid.NewGuid().ToString() }; var preMapping4 = target["[4]"]; var result = Mapper.Map(source).Over(target); result.Count.ShouldBe(4); result["[0]"].ShouldBe(source.First().ToString()); result["[1]"].ShouldBe(source.Second().ToString()); result["[2]"].ShouldBe(source.Third().ToString()); result["[4]"].ShouldBe(preMapping4); }
public void ShouldMergeSimpleTypeCollectionFromSimpleTypeDictionaryImplementationEntries() { var source = new StringKeyedDictionary <int> { ["Blah"] = 5, ["Value[0]"] = 20, ["Value[1]"] = 30 }; var target = new PublicField <ICollection <short?> > { Value = new List <short?> { 10, 20 } }; var result = Mapper.Map(source).OnTo(target); result.Value.ShouldNotContain((short?)5); result.Value.ShouldBe((short?)10, (short?)20, (short?)30); }
public void ShouldMapFromASimpleTypeDictionaryImplementationToAnIDictionary() { var source = new StringKeyedDictionary <string> { ["One"] = "One!", ["Two"] = "Two!", ["Three"] = "Three!", }; var result = Mapper.Map(source).ToANew <IDictionary <string, string> >(); result.Count.ShouldBe(3); result.ShouldContainKey("One"); result["One"].ShouldBe("One!"); result.ShouldContainKey("Two"); result["Two"].ShouldBe("Two!"); result.ShouldContainKey("Three"); result["Three"].ShouldBe("Three!"); }
public void AccessTest(StringComparison?comparison) { const int count = 100_000; StringComparer sc = null; StringSegmentComparer ssc = null; if (comparison != null) { #if NETFRAMEWORK || NETSTANDARD2_0 sc = comparison.Value switch { StringComparison.Ordinal => StringComparer.Ordinal, StringComparison.OrdinalIgnoreCase => StringComparer.OrdinalIgnoreCase, StringComparison.InvariantCulture => StringComparer.InvariantCulture, StringComparison.InvariantCultureIgnoreCase => StringComparer.InvariantCultureIgnoreCase, _ => throw new ArgumentOutOfRangeException(nameof(comparison)) }; #else sc = StringComparer.FromComparison(comparison.Value); #endif ssc = StringSegmentComparer.FromComparison(comparison.Value); } Dictionary <string, int> dictionary = Enumerable.Range(0, count).ToDictionary(i => i.ToString(CultureInfo.InvariantCulture), sc); var strDict = new StringKeyedDictionary <int>(dictionary, ssc); new IteratorPerformanceTest <int> { TestName = "Indexer access test", Iterations = count } .AddCase(i => dictionary[i.ToString(CultureInfo.InvariantCulture)], "Dictionary read") .AddCase(i => strDict[i.ToString(CultureInfo.InvariantCulture)], "StringKeyedDictionary read (string)") .AddCase(i => strDict[i.ToString(CultureInfo.InvariantCulture).AsSegment()], "StringKeyedDictionary read (StringSegment)") #if !(NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0) .AddCase(i => strDict[i.ToString(CultureInfo.InvariantCulture).AsSpan()], "StringKeyedDictionary read (ReadOnlySpan<char>)") #endif .DoTest() .DumpResults(Console.Out); }
/// <summary> /// Tries to convert the string representation of the name or numeric value of one or more enumerated values to an equivalent enumerated object. /// In case of success the return value is <see langword="true"/> and parsed <see langword="enum"/> is returned in <paramref name="result"/> parameter. /// </summary> /// <param name="value">The <see cref="string">string</see> representation of the enumerated value or values to parse.</param> /// <param name="separator">In case of more values specifies the separator among the values. If <see langword="null"/> or is empty, then comma (<c>,</c>) separator is used.</param> /// <param name="ignoreCase">If <see langword="true"/>, ignores case; otherwise, regards case.</param> /// <param name="result">Returns the default value of <typeparamref name="TEnum"/>, if return value is <see langword="false"/>; otherwise, the parsed <see langword="enum"/> value.</param> /// <returns><see langword="false"/> if the <see cref="string">string</see> in <paramref name="value"/> parameter cannot be parsed as <typeparamref name="TEnum"/>; otherwise, <see langword="true"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception> public static bool TryParse(string value, string separator, bool ignoreCase, out TEnum result) { if (value == null) { Throw.ArgumentNullException(Argument.value); } // simple name match test (always case-sensitive) if (NameValuePairs.TryGetValue(value, out result)) { return(true); } var s = new StringSegmentInternal(value); s.Trim(); result = default(TEnum); if (s.Length == 0) { return(false); } // simple numeric value char c = s[0]; if (((c >= '0' && c <= '9') || c == '-' || c == '+') && s.TryParseIntQuick(underlyingInfo.IsSigned, underlyingInfo.MaxValue, out ulong numericValue)) { result = converter.ToEnum(numericValue); return(true); } // rest: flags enum or ignored case if (String.IsNullOrEmpty(separator)) { separator = EnumExtensions.DefaultParseSeparator; } ulong acc = 0UL; StringKeyedDictionary <ulong> dict = ignoreCase ? NameRawValuePairsIgnoreCase : NameRawValuePairs; while (s.TryGetNextSegment(separator, out StringSegmentInternal token)) { token.Trim(); if (token.Length == 0) { return(false); } // literal token found in dictionary if (dict.TryGetValue(token, out ulong tokens)) { acc |= tokens; continue; } // checking if is numeric token c = token[0]; if (((c >= '0' && c <= '9') || c == '-' || c == '+') && token.TryParseIntQuick(underlyingInfo.IsSigned, underlyingInfo.MaxValue, out numericValue)) { acc |= numericValue; continue; } // none of above return(false); } result = converter.ToEnum(acc); return(true); }
public void OverloadConflictTest() { var dObj = new Dictionary <string, object>(); var dConv = new Dictionary <string, IConvertible>(); #if !(NET35 || NET40) IReadOnlyDictionary <string, IConvertible> dConvRo = dConv; IReadOnlyDictionary <string, object> dObjRo = dObj; #endif IDictionary <string, IConvertible> dConvRw = dConv; IDictionary <string, object> dObjRw = dObj; // the extensions Assert.IsNull(dConv.GetValueOrDefault("")); Assert.IsNull(dObj.GetValueOrDefault("")); #if !(NET35 || NET40) Assert.IsNull(dConvRo.GetValueOrDefault("")); Assert.IsNull(dObjRo.GetValueOrDefault("")); Assert.AreEqual(0, dObjRo.GetValueOrDefault <int>("")); #endif Assert.IsNull(dConvRw.GetValueOrDefault("")); Assert.IsNull(dObjRw.GetValueOrDefault("")); // actual value extensions (so the GetValueOrDefault methods can have the same behavior as the .NET Core/Standard methods) Assert.AreEqual(0, dObjRw.GetValueOrDefault <int>("")); Assert.AreEqual(1, dConv.GetActualValueOrDefault("", 1)); Assert.AreEqual(1, dObj.GetActualValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dConvRo.GetActualValueOrDefault("", 1)); #endif Assert.AreEqual(1, dConvRw.GetActualValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dObjRo.GetActualValueOrDefault("", 1)); #endif Assert.AreEqual(1, dObjRw.GetActualValueOrDefault("", 1)); var dictConv = new StringKeyedDictionary <IConvertible>(); var dictObj = new StringKeyedDictionary <object>(); #if !(NET35 || NET40) IStringKeyedReadOnlyDictionary <IConvertible> dictConvRo = dictConv; IStringKeyedReadOnlyDictionary <object> dictObjRo = dictObj; #endif IStringKeyedDictionary <IConvertible> dictConvRw = dictConv; IStringKeyedDictionary <object> dictObjRw = dictObj; // As StringKeyedDictionary defines these methods as well, these are not the extensions Assert.IsNull(dictConv.GetValueOrDefault("")); Assert.IsNull(dictObj.GetValueOrDefault("")); #if !(NET35 || NET40) Assert.IsNull(dictConvRo.GetValueOrDefault("")); Assert.IsNull(dictObjRo.GetValueOrDefault("")); Assert.AreEqual(0, dictObjRo.GetValueOrDefault <int>("")); #endif Assert.IsNull(dictConvRw.GetValueOrDefault("")); Assert.IsNull(dictObjRw.GetValueOrDefault("")); Assert.AreEqual(0, dictObjRw.GetValueOrDefault <int>("")); // But the extensions work seamlessly as for normal dictionaries Assert.AreEqual(1, dictConv.GetActualValueOrDefault("", 1)); Assert.AreEqual(1, dictObj.GetActualValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictConvRo.GetActualValueOrDefault("", 1)); #endif Assert.AreEqual(1, dictConvRw.GetActualValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictObjRo.GetActualValueOrDefault("", 1)); #endif Assert.AreEqual(1, dictObjRw.GetActualValueOrDefault("", 1)); // As here no need to be compatible with library methods, hese GetValueOrDefault can work the same way as GetActualValueOrDefault Assert.AreEqual(1, dictConv.GetValueOrDefault("", 1)); Assert.AreEqual(1, dictObj.GetValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictConvRo.GetValueOrDefault("", 1)); #endif Assert.AreEqual(1, dictConvRw.GetValueOrDefault("", 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictObjRo.GetValueOrDefault("", 1)); #endif Assert.AreEqual(1, dictObjRw.GetValueOrDefault("", 1)); // StringSegment overloads Assert.IsNull(dictConv.GetValueOrDefault("".AsSegment())); Assert.IsNull(dictObj.GetValueOrDefault("".AsSegment())); #if !(NET35 || NET40) Assert.IsNull(dictConvRo.GetValueOrDefault("".AsSegment())); Assert.IsNull(dictObjRo.GetValueOrDefault("".AsSegment())); Assert.AreEqual(0, dictObjRo.GetValueOrDefault <int>("".AsSegment())); #endif Assert.IsNull(dictConvRw.GetValueOrDefault("".AsSegment())); Assert.IsNull(dictObjRw.GetValueOrDefault("".AsSegment())); Assert.AreEqual(0, dictObjRw.GetValueOrDefault <int>("".AsSegment())); Assert.AreEqual(1, dictConv.GetValueOrDefault("".AsSegment(), 1)); Assert.AreEqual(1, dictObj.GetValueOrDefault("".AsSegment(), 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictConvRo.GetValueOrDefault("".AsSegment(), 1)); #endif Assert.AreEqual(1, dictConvRw.GetValueOrDefault("".AsSegment(), 1)); #if !(NET35 || NET40) Assert.AreEqual(1, dictObjRo.GetValueOrDefault("".AsSegment(), 1)); #endif Assert.AreEqual(1, dictObjRw.GetValueOrDefault("".AsSegment(), 1)); #if !(NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2_0) // Span overloads Assert.IsNull(dictConv.GetValueOrDefault("".AsSpan())); Assert.IsNull(dictObj.GetValueOrDefault("".AsSpan())); Assert.IsNull(dictConvRo.GetValueOrDefault("".AsSpan())); Assert.IsNull(dictObjRo.GetValueOrDefault("".AsSpan())); Assert.AreEqual(0, dictObjRo.GetValueOrDefault <int>("".AsSpan())); Assert.IsNull(dictConvRw.GetValueOrDefault("".AsSpan())); Assert.IsNull(dictObjRw.GetValueOrDefault("".AsSpan())); Assert.AreEqual(0, dictObjRw.GetValueOrDefault <int>("".AsSpan())); Assert.AreEqual(1, dictConv.GetValueOrDefault("".AsSpan(), 1)); Assert.AreEqual(1, dictObj.GetValueOrDefault("".AsSpan(), 1)); Assert.AreEqual(1, dictConvRo.GetValueOrDefault("".AsSpan(), 1)); Assert.AreEqual(1, dictConvRw.GetValueOrDefault("".AsSpan(), 1)); Assert.AreEqual(1, dictObjRo.GetValueOrDefault("".AsSpan(), 1)); Assert.AreEqual(1, dictObjRw.GetValueOrDefault("".AsSpan(), 1)); #endif }