C#List克隆复制副本及比较是否相等

一、复制克隆      

       在编程中时常遇到想要去操作某个List集合而又不想破坏原有List的情况。如果仅仅是新建一个新List,将旧List的值赋值给新List的话,改变复制后的List,那么原有的List也会变化,并没有起到备份原始数据的作用,对于没有嵌套的List,可以采用遍历重新赋值的方法去赋值(传递的是值类型,并非引用类型),若List内的数据是一个类的话,赋值的时候需要重新实例化才行。但如果是嵌套的List列表,遍历这种方法就麻烦了很多。

  拓展:c#中有两种基本类型,它们分别是值类型和引用类型;其中类和数组属于引用类型。

因此,常见的对List进行复制克隆的方法如下:

1、值类型集合的复制克隆

private void Test()
{
    List<object> lis = new List<object> { 1,2 };
    List<object> lis1 = lis;     //结果["sss",2]
    //方法一
    List<object> lis2 = new List<object>();
    lis.ForEach(x=>lis2.Add(x));    //结果[1,2]
    //方法二
    List<object> lis3 = lis.ToArray().ToList();   //结果[1,2]

    //变化第一个值
    lis[0] = "sss";
}

2、引用类型集合的复制克隆

[Serializable]
public class People
{
    public string Name { get; set; }
    public int Age { get; set; }
}

private void Test()
{
    List<People> peoples1 = new List<People> { new People { Name = "张三", Age = 10 }, new People { Name = "小红", Age = 10 } };
    //方法一 copy  peoples1 to peoples2
    List<People> peoples2 = peoples1.ConvertAll<People>(x => { return new People { Name = x.Name, Age = x.Age }; });
    //方法二
    List<People> peoples3 = Clone(peoples1) as List<People>;
    //方法三 需要引用Newtonsoft.Json.dll
    List<People> peoples4= JsonConvert.DeserializeObject<List<People>>(JsonConvert.SerializeObject(peoples1));
}
/// <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);
}

二、比较两个List集合是否相等

根据相等比较器确定两个序列是否相等。

1、值类型比较

/// <summary>
/// 值类型集合比较
/// </summary>
private void Test()
{
    List<int> lis1 = new List<int> { 1, 2, 3 };
    List<int> lis2 = new List<int> { 1, 2, 3 };
    var c = lis1.SequenceEqual(lis2); //结果 true
}

2、对象集合比较

//如果要比较序列中对象的实际数据而不是仅仅比较它们的引用,则必须在类中实现IEqualityComparer<T> 泛型接口
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;
    }     
}
        
/// <summary>
/// 对象集合比较
/// </summary>
private void Test()
{
    List<People> peoples1 = new List<People> { new People { Name = "张三", Age = 10 }, new People { Name = "小红", Age = 10 } };
    List<People> peoples2 = new List<People> { new People { Name = "张三", Age = 10 }, new People { Name = "小红", Age = 10 } };
    var b = peoples1.SequenceEqual(peoples2); //true
}

 

C#中,比较`List<T>`对象是否相等通常涉及到检查两个列表的内容、顺序以及元素类型是否都相同。直接使用“==”操作符来进行比较是不够的,因为这只会检查引用是否指向相同的内存地址,并不会检查内容是否一致。 ### 比较列表的基本方法 有两种常见的方式来比较两个`List<T>`: #### 方式一:序列化方法 一种直观的方式是将两个列表转换成字符串或其他序列化的形式然后进行比较。这种方式依赖于列表的序列化特性: ```csharp public static bool AreListsEqual(List<object> firstList, List<object> secondList) { var firstListSerialized = SerializeList(firstList); var secondListSerialized = SerializeList(secondList); return firstListSerialized.SequenceEqual(secondListSerialized); } private static string SerializeList(List<object> list) { // 示例序列化逻辑,可以使用Json.NET等库进行序列化 var jsonSerializerSettings = new JsonSerializerSettings { Formatting = Formatting.None }; using (var writer = new StringWriter()) { JsonWriterExtensions.WriteValue(writer, list, jsonSerializerSettings); return writer.ToString(); } } ``` #### 方式二:迭代比较每个元素 另一种更直接的方法是在循环中逐个比较列表中的元素: ```csharp public static bool AreListsEqual(List<T> firstList, List<T> secondList) { if (firstList.Count != secondList.Count) return false; for (int i = 0; i < firstList.Count; i++) { if (!EqualityComparer<T>.Default.Equals(firstList[i], secondList[i])) { return false; } } return true; } ``` 在这个方法中,我们使用了`EqualityComparer<T>.Default.Equals`来比较元素的值,这是一个安全且高效的比较方式。 ### 相关问题: 1. 如果列表包含复杂对象或嵌套结构,如何进行深度比较? 2. 使用序列化方法可能会遇到性能问题,特别是对于大型列表,有什么优化策略吗? 3. 在哪种场景下更适合使用上述任意一种方法进行列表比较
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值