服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 使用Dictionary复制克隆副本及比较是否相等

C# 使用Dictionary复制克隆副本及比较是否相等

2022-10-21 13:05秋漓 C#

这篇文章主要介绍了C# 使用Dictionary复制克隆副本及比较是否相等,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

一、复制克隆

用等号直接Dictionary1 = Dictionary2,复制过去的是地址(赋址),这时改变Dictionary2,Dictionary1也会被改变。普遍的是我们常常在改变复制后的值时不希望改变原有的值。这时就需要赋值而不是赋址。可用下列方法进行赋值:

?
1
2
3
4
5
6
7
8
9
10
private void Test()
{
 Dictionary<string, string> dic = new Dictionary<string, string> { { "A", "a" }, { "B", "b" } };
 //方法一
 Dictionary<string, string> dic1 = new Dictionary<string, string>(dic);
 //方法二
 Dictionary<string, string> dic2 = Clone(dic) as Dictionary<string, string>;
 //方法三 --需要引用Newtonsoft.Json.dll
 Dictionary<string, string> dic3 = JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonConvert.SerializeObject(dic2));
}

采用序列化和反序列化

?
1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 得到一个对象的克隆(二进制的序列化和反序列化)--需要标记可序列化
/// </summary>
public static object Clone(object obj)
{
 MemoryStream memoryStream = new MemoryStream();
 BinaryFormatter formatter = new BinaryFormatter();
 formatter.Serialize(memoryStream, obj);
 memoryStream.Position = 0;
 return formatter.Deserialize(memoryStream);
}

当值为引用类型时

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[Serializable]
public class People : IEquatable<People>
{
 public string Name { get; set; }
 public int Age { get; set; }
 public bool Equals(People other)
 {
  if (other is null)
   return false;
  return this.Name == other.Name && this.Age == other.Age;
 }
}
 
private void Test()
{
 Dictionary<string, People> dic = new Dictionary<string, People> { { "A", new People {Name="SD",Age=0 } }, { "B", new People { Name = "FD", Age = 1 } } };
 //方法一
 Dictionary<string, People> dic2 = Clone(dic) as Dictionary<string, People>;
 //方法二 --需要引用Newtonsoft.Json.dll
 Dictionary<string, People> dic3 = JsonConvert.DeserializeObject<Dictionary<string, People>>(JsonConvert.SerializeObject(dic2));
}

二、比较两个Dictionary是否相等

?
1
2
3
4
5
6
7
8
9
10
/// <summary>
/// 比较
/// </summary>
private void Test()
{
 Dictionary<string, object> dic = new Dictionary<string, object> { { "A", 1 }, { "B", "b" } };
 Dictionary<string, object> dic2 = new Dictionary<string, object> { { "A", 1 }, { "B", "b" } };
 var a = dic.Equals(dic2); //结果 false
 var b = dic.SequenceEqual(dic2); //结果 true
}

补充知识:C#中的深复制和浅复制(在C#中克隆对象)

C# 支持两种类型:“值类型”和“引用类型”。

值类型(Value Type)(如 char、int 和 float)、枚举类型和结构类型。

引用类型(Reference Type) 包括类 (Class) 类型、接口类型、委托类型和数组类型。

如何来划分它们?

以它们在计算机内存中如何分配来划分

值类型与引用类型的区别?

1,值类型的变量直接包含其数据,

2,引用类型的变量则存储对象引用。

对于引用类型,两个变量可能引用同一个对象,因此对一个变量的操作可能影响另一个变量所引用的对象。对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响另一个变量。

值类型隐式继承自System.ValueType 所以不能显示让一个结构继承一个类,C#不支持多继承

堆栈(stack)是一种先进先出的数据结构,在内存中,变量会被分配在堆栈上来进行操作。

堆(heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,

会将对象的地址传给堆栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)。

关于对象克隆的所设计到知识点

浅拷贝:

是指将对象中的所有字段逐字复杂到一个新对象

对值类型字段只是简单的拷贝一个副本到目标对象,改变目标对象中值类型字段的值不会反映到原始对象中,因为拷贝的是副本

对引用型字段则是指拷贝他的一个引用到目标对象。改变目标对象中引用类型字段的值它将反映到原始对象中,因为拷贝的是指向堆是上的一个地址

深拷贝:

深拷贝与浅拷贝不同的是对于引用字段的处理,深拷贝将会在新对象中创建一个新的对象和原始对象中对应字段相同(内容相同)的字段,也就是说这个引用和原始对象的引用是不同, 我们改变新

对象中这个字段的时候是不会影响到原始对象中对应字段的内容。

浅复制: 实现浅复制需要使用Object类的MemberwiseClone方法用于创建一个浅表副本

深复制: 须实现 ICloneable接口中的Clone方法,且需要需要克隆的对象加上[Serializable]特性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace DeepCopy
{
 class DrawBase : System.Object, ICloneable
 {
  public List<string> listName = new List<string>();
  public string name = "old";
  public DrawBase()
  {
  }
  public object Clone()
  {
   //任选一个
   return this as object//引用同一个对象
   //return this.MemberwiseClone(); //浅复制
   //return new DrawBase() as object;//深复制
  }
 }
 class Program
 {
  static void Main(string[] args)
  {
   DrawBase rect = new DrawBase();
   Console.WriteLine(rect.name);
   DrawBase line = rect.Clone() as DrawBase;
   line.name = "new";
   line.listName.Add("123");
   Console.WriteLine(rect.name);
   Console.WriteLine(rect.listName.Count);
   Console.ReadLine();
  }
 }
}

当return this as object;

输出:old,new,1

说明:方法总是引用同一个对象,因此相应的堆内存上的值会改变

当return this.MemberwiseClone();

输出:old,old,1

说明:对于内部的Class的对象和数组,会Copy地址一份。[从而改变B时,A也被改变了]而对于其它内置的int/string/Enum/struct/object类型,则进行值copy。

当return new DrawBase() as object;

输出:old,old,0

说明:完全是创建一个新对象

总结:

浅拷贝:是指将对象中的所有字段逐字复杂到一个新对象。

对值类型字段只是简单的拷贝一个副本到目标对象,改变目标对象中值类型字段的值不会反映到原始对象中,因为拷贝的是副本;

对引用型字段则是指拷贝他的一个引用到目标对象。改变目标对象中引用类型字段的值它将反映到原始对象中,因为拷贝的是指向堆是上的一个地址;

深拷贝:深拷贝与浅拷贝不同的是对于引用字段的处理,深拷贝将会在新对象中创建一个新的对象和原始对象中对应字段相同(内容相同)的字段,也就是说这个引用和原始对象的引用是不同, 我们改变新对象中这个字段的时候是不会影响到原始对象中对应字段的内容。

以上这篇C# 使用Dictionary复制克隆副本及比较是否相等就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/qq_33459369/article/details/89365634

延伸 · 阅读

精彩推荐
  • C#C#窗体传值代码方法

    C#窗体传值代码方法

    在本篇文章里小编给大家整理的是关于C#窗体传值代码内容,需要的朋友们可以跟着学习参考下。...

    .NET开发菜鸟3752022-08-27
  • C#C#中字段、属性、只读、构造函数赋值、反射赋值的问题

    C#中字段、属性、只读、构造函数赋值、反射赋值的问题

    这篇文章主要介绍了C#中字段、属性、只读、构造函数赋值、反射赋值的问题 ,非常不错,具有一定的参考借鉴借鉴价值,需要的朋友可以参考下...

    GetPower8082022-02-28
  • C#C#串口编程实例代码

    C#串口编程实例代码

    这篇文章主要为大家详细介绍了C#串口编程实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    温暖的小明7382021-12-03
  • C#C#下listview如何插入图片

    C#下listview如何插入图片

    这篇文章主要为大家详细介绍了C#下listview如何插入图片,如何在listview中插入图片的每一个步骤为大家分享,感兴趣的朋友可以参考一下...

    C#教程网5312021-11-21
  • C#人脸认证源码faceIdentify详解

    人脸认证源码faceIdentify详解

    这篇文章主要为大家详细介绍了人脸认证源码faceIdentify的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    穆雄雄6892022-08-04
  • C#C#文件下载实例代码(适用于各个浏览器)

    C#文件下载实例代码(适用于各个浏览器)

    本文给大家分享一段实例代码关于css实现文件下载功能,需要的的朋友参考下吧...

    陈逸子风8552022-01-04
  • C#C#中char和string的入门使用教程

    C#中char和string的入门使用教程

    这篇文章主要给大家介绍了关于C#中char和string的入门使用教程,文中通过示例代码以及图文介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价...

    NanKingQG11222022-09-27
  • C#C#控制台应用程序中输出彩色字体

    C#控制台应用程序中输出彩色字体

    这篇文章主要为大家详细介绍了C#控制台应用程序中输出彩色字体的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    雲霏霏8642022-01-06