最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典

 更新時(shí)間:2021年02月01日 08:57:07   作者:WeihanLi  
這篇文章主要介紹了C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下

Intro

今天在項(xiàng)目里遇到一個(gè)需求,大概是這樣的我要比較兩個(gè) JSON 字符串是不是相等,JSON 字符串其實(shí)是一個(gè) Dictionary<string, string> 但是順序可能不同,和上一篇 record 使用場(chǎng)景 中的第一個(gè)需求類似,前面我們介紹過(guò)使用 record 可以比較方便的解決,但是我們的項(xiàng)目是 .netcoreapp3.1 的,不能使用 record,如何比較方便的比較呢?我們能否自己實(shí)現(xiàn)一個(gè)類似于 record 的類型,基于值去比較呢?于是就有了本文的探索

StringValueDictioanry

實(shí)現(xiàn)了一個(gè)基于值進(jìn)行比較的字典,實(shí)現(xiàn)代碼如下,實(shí)現(xiàn)的比較簡(jiǎn)單,涉及到一些簡(jiǎn)單的知識(shí)點(diǎn),平時(shí)不怎么用已經(jīng)忘了怎么寫(xiě)了,通過(guò)寫(xiě)下面的代碼又學(xué)習(xí)了一下

先來(lái)看測(cè)試代碼吧,測(cè)試代碼如下:

[Fact]
public void EqualsTest()
{
 var abc = new { Id = 1, Name = "Tom" };
 var dic1 = StringValueDictionary.FromObject(abc);
 var dic2 = StringValueDictionary.FromObject(new Dictionary<string, 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 Dictionary<string, object>()
 {
 {"Id", 1},
 {"Name", "Tom" },
 });
 var set = new HashSet<StringValueDictionary>();
 set.Add(dic1);
 set.Add(dic2);

 Assert.Single(set);
}

[Fact]
public void CloneTest()
{
 var dic1 = StringValueDictionary.FromObject(new Dictionary<string, 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);
 Dictionary<string, string> dictionary = stringValueDictionary;
 Assert.Equal(stringValueDictionary.Count, dictionary.Count);

 var dic2 = StringValueDictionary.FromObject(dictionary);

 Assert.Equal(dic2, stringValueDictionary);
 Assert.True(dic2 == stringValueDictionary);
}

從上面的代碼可能大概能看出一些實(shí)現(xiàn),重寫(xiě)了默認(rèn)的 EqualsGetHashCode,并重載了“==” 運(yùn)算符,并且實(shí)現(xiàn)了一個(gè)從 StringValueDictionary Dictionary 的隱式轉(zhuǎn)換,來(lái)看下面的實(shí)現(xiàn)代碼:

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[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 IDictionary<string, string?> dictionary)
 {
  return new StringValueDictionary(dictionary);
 }
 if (obj is IDictionary<string, 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.JsonToObject<Dictionary<string, 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 Dictionary<string, 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 Dictionary<string, string?>(StringValueDictionary dictionary)
 {
 return dictionary._dictionary;
 }
}

More

上述代碼實(shí)現(xiàn)的有點(diǎn)粗糙,可能會(huì)有一些問(wèn)題,僅供參考

以上代碼基本實(shí)現(xiàn)了基于想要的值的相等性比較以及 Clone(復(fù)制、克隆)的目標(biāo)

實(shí)現(xiàn)相等性比較的時(shí)候,EqualsGetHashCode 方法也要重寫(xiě),如果沒(méi)有重寫(xiě) GetHashCode,編譯器也會(huì)給出警告,如果沒(méi)有重寫(xiě) GetHashCode 在實(shí)際在 HashSet 或者 Dictionary 里可能會(huì)出現(xiàn)重復(fù) key

重載運(yùn)算符的時(shí)候需要一個(gè)靜態(tài)方法,"==" 和 "!=" 是一對(duì)操作運(yùn)算符,如果要實(shí)現(xiàn)兩個(gè)都要實(shí)現(xiàn),不能只實(shí)現(xiàn)其中一個(gè)

implicit 也算是一個(gè)特殊的運(yùn)算符,巧妙的使用隱式轉(zhuǎn)換可以大大簡(jiǎn)化代碼的寫(xiě)法,StackExchange.Redis 中就使用了 implicit 來(lái)實(shí)現(xiàn) RedisValuestring 等其他常用類型的隱式轉(zhuǎn)換

References

https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Models/StringValueDictionary.cs
https://github.com/WeihanLi/WeihanLi.Common/blob/dev/test/WeihanLi.Common.Test/ModelsTest/StringValueDictionaryTest.cs

以上就是C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典的詳細(xì)內(nèi)容,更多關(guān)于c# 實(shí)現(xiàn)值相等性比較的字典的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#代碼實(shí)現(xiàn)PDF文檔操作類

    C#代碼實(shí)現(xiàn)PDF文檔操作類

    本篇文章給大家介紹使用pdf文檔操作C#代碼,本文代碼非常簡(jiǎn)單,代碼附有注釋,需要注意的是:需要添加itextsharp.dll引用才可以正常通過(guò)編譯,感興趣的朋友可以參考下
    2015-10-10
  • C# 操作 MongoDB的示例demo

    C# 操作 MongoDB的示例demo

    這篇文章主要介紹了C# 操作 MongoDB的示例demo,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下
    2020-12-12
  • C#基礎(chǔ)教程之類class與結(jié)構(gòu)struct的區(qū)別

    C#基礎(chǔ)教程之類class與結(jié)構(gòu)struct的區(qū)別

    struct是值類型,創(chuàng)建一個(gè)struct類型的實(shí)例被分配在棧上,class是引用類型,創(chuàng)建一個(gè)class類型實(shí)例被分配在托管堆上,下面這篇文章主要給大家介紹了關(guān)于C#基礎(chǔ)教程之類class與結(jié)構(gòu)struct區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • C#生成Word文檔代碼示例

    C#生成Word文檔代碼示例

    這篇文章主要介紹了C#生成Word文檔代碼示例,本文直接給出代碼實(shí)例,需要的朋友可以參考下
    2015-06-06
  • C#調(diào)用SQL?Server中有參數(shù)的存儲(chǔ)過(guò)程

    C#調(diào)用SQL?Server中有參數(shù)的存儲(chǔ)過(guò)程

    這篇文章介紹了C#調(diào)用SQL?Server中有參數(shù)存儲(chǔ)過(guò)程的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • C#的四種基本數(shù)據(jù)類型

    C#的四種基本數(shù)據(jù)類型

    本文主要介紹了C#的四種基本數(shù)據(jù)類型的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • C# 獲取進(jìn)程退出代碼的實(shí)現(xiàn)示例

    C# 獲取進(jìn)程退出代碼的實(shí)現(xiàn)示例

    這篇文章主要介紹了C# 獲取進(jìn)程退出代碼的實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • C#中Dynamic和Dictionary性能比較

    C#中Dynamic和Dictionary性能比較

    開(kāi)發(fā)中需要傳遞變參,考慮使用 dynamic 還是 Dictionary,dynamic 的編碼體驗(yàn)顯著優(yōu)于 Dictionary,如果性能差距不大的話,我會(huì)選擇使用dynamic。下面通過(guò)本文給大家詳細(xì)介紹下C#中Dynamic和Dictionary性能比較,一起看看吧
    2016-11-11
  • Unity通過(guò)代碼修改按鈕點(diǎn)擊效果

    Unity通過(guò)代碼修改按鈕點(diǎn)擊效果

    這篇文章主要為大家詳細(xì)介紹了Unity通過(guò)代碼修改按鈕點(diǎn)擊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 雅虎公司C#筆試題(后半部份才是)

    雅虎公司C#筆試題(后半部份才是)

    雅虎公司C#筆試題(后半部份才是)...
    2007-04-04

最新評(píng)論

昆山市| 读书| 英吉沙县| 三穗县| 岳西县| 南涧| 陆良县| 香港| 曲阜市| 犍为县| 江华| 高密市| 乌兰浩特市| 井冈山市| 驻马店市| 长岛县| 汤阴县| 汉沽区| 宁晋县| 桐梓县| 平武县| 来宾市| 奉新县| 开化县| 明水县| 平安县| 黄平县| 南皮县| 都匀市| 垦利县| 宽甸| 马尔康县| 福建省| 尚志市| 江川县| 连江县| 观塘区| 新丰县| 广宗县| 望江县| 建阳市|