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

本文详细介绍C#中List集合的复制与克隆方法,包括值类型与引用类型的复制策略,以及如何比较两个List集合是否相等。通过具体示例,讲解了不同复制方法的适用场景,以及如何自定义对象的比较逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、复制克隆      

       在编程中时常遇到想要去操作某个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
}

 

<think>我们正在讨论的是在.NET Framework 2.0中克隆List<string>。由于.NET 2.0版本较旧,一些现代的方法(如LINQ)不可用,但我们可以使用基本的方法来实现。 注意:字符串在C#中是不可变的,因此对于List<string>,浅拷贝就足够了,因为即使两个列表共享相同的字符串引用,由于字符串不可变,修改一个列表中的字符串(实际上是替换)不会影响另一个列表中的字符串。 在.NET Framework 2.0中,我们可以使用以下方法克隆List<string>: 方法1:使用List<T>的构造函数,它接受一个IEnumerable<T>参数。 List<string> clonedList = new List<string>(originalList); 方法2:使用List<T>的GetRange方法,获取整个范围。 List<string> clonedList = originalList.GetRange(0, originalList.Count); 方法3:手动遍历并添加到新列表(虽然不简洁,但也是可行的)。 其中,方法1是最简单和常用的。 代码示例: ```csharp // 原始列表 List<string> originalList = new List<string>(); originalList.Add("apple"); originalList.Add("banana"); originalList.Add("cherry"); // 克隆列表 List<string> clonedList = new List<string>(originalList); // 修改克隆列表的第一个元素(不会影响原列表,因为字符串是不可变的,这里实际上是替换了引用) clonedList[0] = "orange"; // 验证 Console.WriteLine("Original List:"); foreach (string s in originalList) { Console.WriteLine(s); // 输出apple, banana, cherry } Console.WriteLine("Cloned List:"); foreach (string s in clonedList) { Console.WriteLine(s); // 输出orange, banana, cherry } ``` 说明: - 使用构造函数`new List<string>(originalList)`会创建一个新列表,并将原列表的所有元素复制到新列表中。由于是浅拷贝,复制的是字符串的引用。但由于字符串的不可变性,当修改克隆列表中的某个元素(即用一个新的字符串替换)时,原列表中的对应元素不会改变。 - 这种方法的时间复杂度是O(n),其中n是列表的元素个数。 注意事项: - 在.NET Framework 2.0中,我们没有LINQ的`ToList()`方法(因为LINQ是.NET 3.5引入的),所以不能使用`originalList.ToList()`。 - 如果列表中的元素是可变引用类型,那么浅拷贝会导致两个列表共享相同的对象引用,修改其中一个列表中的对象的属性会影响到另一个列表。但这里元素是字符串,所以没有问题。 相关问题: 1. 在C#中,如何克隆一个包含自定义对象的List<T>(深拷贝)? 2. .NET Framework 2.0中还有哪些集合复制的方法? 3. 字符串的不可变性在集合复制中有什么优势?</think>### C# .NET Framework 2.0 克隆 List<string> 的方法 在 .NET Framework 2.0 中克隆 `List<string>` 对象,由于字符串的**不可变性**特性,使用浅拷贝(shallow copy)即可安全实现。以下是三种常用方法: #### 方法1:使用构造函数(推荐) ```csharp List<string> originalList = new List<string> { "A", "B", "C" }; List<string> clonedList = new List<string>(originalList); // 创建新列表并复制元素 ``` #### 方法2:使用 `GetRange()` 方法 ```csharp List<string> clonedList = originalList.GetRange(0, originalList.Count); // 获取整个范围 ``` #### 方法3:手动遍历复制 ```csharp List<string> clonedList = new List<string>(originalList.Count); foreach (string item in originalList) { clonedList.Add(item); // 逐元素添加 } ``` #### 验证示例 ```csharp // 修改克隆列表 clonedList[0] = "X"; Console.WriteLine("原列表: " + string.Join(",", originalList)); // 输出: A,B,C Console.WriteLine("克隆列表: " + string.Join(",", clonedList)); // 输出: X,B,C ``` ### 关键说明 1. **字符串不可变性**: 由于字符串在 C# 中不可变,修改克隆列表中的元素(如 `clonedList[0] = "X"`)会创建新字符串对象,不会影响原列表[^1]。 2. **性能对比**: | 方法 | 时间复杂度 | 内存效率 | |------|------------|----------| | 构造函数 | $O(n)$ | 最优 | | GetRange | $O(n)$ | 中等 | | 手动遍历 | $O(n)$ | 最低 | 3. **与数组克隆的区别**: `List<T>` 没有内置的 `Clone()` 方法(数组有),需通过上述方式实现[^3]。 ### 注意事项 - 对于**可变引用类型**(非字符串),这些方法仅执行浅拷贝,需要额外实现深拷贝 - 在 .NET 2.0 中**不可用** LINQ 的 `.ToList()` 或 `.ToArray()` 方法(需 .NET 3.5+) ### 相关问题 1. 在 .NET 2.0 中如何克隆包含自定义对象的 `List<T>`? 2. 字符串的不可变性如何影响集合操作的安全性? 3. .NET Framework 2.0 与更高版本在集合操作上有哪些主要差异? 4. 如何为自定义集合实现深拷贝功能?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值