毕业设计代做网站代码,有人上相亲网站做传销燕窝,跨境电商开店要多少钱,网站建设论文的结论C# 实现一个基于值相等性比较的字典Intro今天在项目里遇到一个需求#xff0c;大概是这样的我要比较两个 JSON 字符串是不是相等#xff0c;JSON 字符串其实是一个 Dictionarystring, string 但是顺序可能不同#xff0c;和上一篇 record 使用场景中的第一个需求类似… C# 实现一个基于值相等性比较的字典Intro今天在项目里遇到一个需求大概是这样的我要比较两个 JSON 字符串是不是相等JSON 字符串其实是一个 Dictionarystring, string 但是顺序可能不同和上一篇 record 使用场景中的第一个需求类似前面我们介绍过使用 record 可以比较方便的解决但是我们的项目是 .netcoreapp3.1 的不能使用 record如何比较方便的比较呢我们能否自己实现一个类似于 record 的类型基于值去比较呢于是就有了本文的探索StringValueDictioanry实现了一个基于值进行比较的字典实现代码如下实现的比较简单涉及到一些简单的知识点平时不怎么用已经忘了怎么写了通过写下面的代码又学习了一下先来看测试代码吧测试代码如下[Fact]
public void EqualsTest()
{var abc new { Id 1, Name Tom };var dic1 StringValueDictionary.FromObject(abc);var dic2 StringValueDictionary.FromObject(new Dictionarystring, object(){{Name, Tom },{Id, 1},});Assert.True(dic1 dic2);Assert.Equal(dic1, dic2);
}[Fact]
public void DistinctTest()
{var abc new { Id 1, Name Tom };var dic1 StringValueDictionary.FromObject(abc);var dic2 StringValueDictionary.FromObject(new Dictionarystring, object(){{Id, 1},{Name, Tom },});var set new HashSetStringValueDictionary();set.Add(dic1);set.Add(dic2);Assert.Single(set);
}[Fact]
public void CloneTest()
{var dic1 StringValueDictionary.FromObject(new Dictionarystring, object(){{Id, 1},{Name, Tom }});var dic2 dic1.Clone();Assert.False(ReferenceEquals(dic1, dic2));Assert.True(dic1 dic2);
}[Fact]
public void ImplicitConvertTest()
{var abc new { Id 1, Name Tom };var stringValueDictionary StringValueDictionary.FromObject(abc);Dictionarystring, string dictionary stringValueDictionary;Assert.Equal(stringValueDictionary.Count, dictionary.Count);var dic2 StringValueDictionary.FromObject(dictionary);Assert.Equal(dic2, stringValueDictionary);Assert.True(dic2 stringValueDictionary);
}
从上面的代码可能大概能看出一些实现重写了默认的 Equals 和 GetHashCode并重载了“” 运算符并且实现了一个从 StringValueDictionary 到 Dictionary 的隐式转换来看下面的实现代码public sealed class StringValueDictionary : IEquatableStringValueDictionary
{private readonly Dictionarystring, string? _dictionary new();private StringValueDictionary(IDictionarystring, string? dictionary){foreach (var pair in dictionary){_dictionary[pair.Key] pair.Value;}}private StringValueDictionary(StringValueDictionary dictionary){foreach (var key in dictionary.Keys){_dictionary[key] dictionary[key];}}public static StringValueDictionary FromObject(object obj){if (obj is null) throw new ArgumentNullException(nameof(obj));if (obj is IDictionarystring, string? dictionary){return new StringValueDictionary(dictionary);}if (obj is IDictionarystring, object? dictionary2){return new StringValueDictionary(dictionary2.ToDictionary(p p.Key, p p.Value?.ToString()));}if (obj is StringValueDictionary dictionary3){return new StringValueDictionary(dictionary3);}return new StringValueDictionary(obj.GetType().GetProperties().ToDictionary(p p.Name, p p.GetValue(obj)?.ToString()));}public static StringValueDictionary FromJson(string json){Guard.NotNull(json, nameof(json));var dic json.JsonToObjectDictionarystring, object?().ToDictionary(x x.Key, x x.Value?.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 Dictionarystring, string.KeyCollection Keys _dictionary.Keys!;public bool Equals(StringValueDictionary? other){if (other is null) return false;if (other.Count ! Count) return false;foreach (var key in _dictionary.Keys){if (!other.ContainsKey(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){stringBuilder.Append(${pair.Key}{pair.Value}_);}return stringBuilder.ToString().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 Dictionarystring, string?(StringValueDictionary dictionary){return dictionary._dictionary;}
}
More上述代码实现的有点粗糙可能会有一些问题仅供参考以上代码基本实现了基于想要的值的相等性比较以及 Clone复制、克隆的目标实现相等性比较的时候Equals 和 GetHashCode 方法也要重写如果没有重写 GetHashCode编译器也会给出警告如果没有重写 GetHashCode 在实际在 HashSet 或者 Dictionary 里可能会出现重复 key重载运算符的时候需要一个静态方法 和 ! 是一对操作运算符如果要实现两个都要实现不能只实现其中一个implicit 也算是一个特殊的运算符巧妙的使用隐式转换可以大大简化代码的写法StackExchange.Redis 中就使用了 implicit 来实现 RedisValue 和 string 等其他常用类型的隐式转换Referenceshttps://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Models/StringValueDictionary.cshttps://github.com/WeihanLi/WeihanLi.Common/blob/dev/test/WeihanLi.Common.Test/ModelsTest/StringValueDictionaryTest.cs