Intro
Today I encountered a requirement in the project. I probably want to compare whether two JSON strings are equal. The JSON string is actually one.Dictionary<string, string>
But the order may be different, andPrevious article record usage scenarioThe first requirement in this article is similar. We have introduced that using record can be more convenient to solve, but our project is.netcoreapp3.1
, cannot be usedrecord
, how to compare more conveniently? Can we implement a similarrecord
What are the types of , based on the values? So this article is explored
StringValueDictioanry
Implemented a dictionary based on values. The implementation code is as follows. The implementation is relatively simple and involves some simple knowledge points. I forgot how to write it if I don’t use it very much. I learned it again by writing the following code.
Let’s take a look at the test code first, the test code is as follows:
[Fact] public void EqualsTest() { var abc = new { Id = 1, Name = "Tom" }; var dic1 = (abc); var dic2 = (new Dictionary<string, object>() { {"Name", "Tom" }, {"Id", 1}, }); (dic1 == dic2); (dic1, dic2); } [Fact] public void DistinctTest() { var abc = new { Id = 1, Name = "Tom" }; var dic1 = (abc); var dic2 = (new Dictionary<string, object>() { {"Id", 1}, {"Name", "Tom" }, }); var set = new HashSet<StringValueDictionary>(); (dic1); (dic2); (set); } [Fact] public void CloneTest() { var dic1 = (new Dictionary<string, object>() { {"Id", 1}, {"Name", "Tom" } }); var dic2 = (); (ReferenceEquals(dic1, dic2)); (dic1 == dic2); } [Fact] public void ImplicitConvertTest() { var abc = new { Id = 1, Name = "Tom" }; var stringValueDictionary = (abc); Dictionary<string, string> dictionary = stringValueDictionary; (, ); var dic2 = (dictionary); (dic2, stringValueDictionary); (dic2 == stringValueDictionary); }
From the above code, we can probably see some implementations, and rewrite the default oneEquals
andGetHashCode
, and overload the "==" operator and implement aStringValueDictionary
arrive Dictionary
Let's look at the following implementation code:
public sealed class StringValueDictionary : IEquatable<StringValueDictionary> { private readonly Dictionary<string, string?> _dictionary = new(); private StringValueDictionary(IDictionary<string, string?> dictionary) { foreach (var pair in dictionary) { _dictionary[] = ; } } private StringValueDictionary(StringValueDictionary dictionary) { foreach (var key in ) { _dictionary[key] = dictionary[key]; } } public static StringValueDictionary FromObject(object obj) { if (obj is null) throw new ArgumentNullException(nameof(obj)); if (obj is IDictionary<string, string?> dictionary) { return new StringValueDictionary(dictionary); } if (obj is IDictionary<string, object?> dictionary2) { return new StringValueDictionary((p => , p => ?.ToString())); } if (obj is StringValueDictionary dictionary3) { return new StringValueDictionary(dictionary3); } return new StringValueDictionary(().GetProperties() .ToDictionary(p => , p => (obj)?.ToString())); } public static StringValueDictionary FromJson(string json) { (json, nameof(json)); var dic = <Dictionary<string, object?>>() .ToDictionary(x => , x => ?.ToString()); return new StringValueDictionary(dic); } public StringValueDictionary Clone() => new(this); public int Count => _dictionary.Count; public bool ContainsKey(string key) => _dictionary.ContainsKey(key) ? _dictionary.ContainsKey(key) : throw new ArgumentOutOfRangeException(nameof(key)); public string? this[string key] => _dictionary[key]; public Dictionary<string, string>.KeyCollection Keys => _dictionary.Keys!; public bool Equals(StringValueDictionary? other) { if (other is null) return false; if ( != Count) return false; foreach (var key in _dictionary.Keys) { if (!(key)) { return false; } if (_dictionary[key] != other[key]) { return false; } } return true; } public override bool Equals(object obj) { return Equals(obj as StringValueDictionary); } public override int GetHashCode() { var stringBuilder = new StringBuilder(); foreach (var pair in _dictionary) { ($"{}={}_"); } return ().GetHashCode(); } public static bool operator ==(StringValueDictionary? current, StringValueDictionary? other) { return current?.Equals(other) == true; } public static bool operator !=(StringValueDictionary? current, StringValueDictionary? other) { return current?.Equals(other) != true; } public static implicit operator Dictionary<string, string?>(StringValueDictionary dictionary) { return dictionary._dictionary; } }
More
The above code is implemented a bit rough and may have some problems. For reference only
The above code basically achieves the goal of comparing the equality of the desired values and Clone (copy, cloning)
When achieving equality comparison,
Equals
andGetHashCode
The method must also be rewritten, if notGetHashCode
, the compiler will also give a warning if it is not rewriteGetHashCode
In factHashSet
orDictionary
There may be duplication inkey
When overloading operators, a static method is needed. "==" and "!=" are a pair of operation operators. If you want to implement both, you cannot only implement one of them.
implicit is also a special operator. Clever use of implicit conversion can greatly simplify the writing of the code.
Used in
implicit
To achieveRedisValue
andstring
Implicit conversions of other common types
References
/WeihanLi//blob/dev/src//Models/
/WeihanLi//blob/dev/test//ModelsTest/
The above is the detailed content of how C# implements a dictionary based on value equality comparison. For more information about c# implementing a dictionary for value equality comparison, please pay attention to my other related articles!