如果要在C#中创建⼀个不可变的List,你会采取什么⽅法?

在 C# 中,创建一个不可变的 List(即创建后无法修改)可以通过以下几种方法实现:


1. 使用 System.Collections.Immutable 命名空间

.NET 提供了 System.Collections.Immutable 包,其中包含不可变集合,包括 ImmutableList<T>

步骤
  • 安装 NuGet 包:System.Collections.Immutable
  • 使用 ImmutableList<T> 类。
示例代码
using System.Collections.Immutable;

class Program
{
    static void Main()
    {
        // 创建一个不可变列表
        var immutableList = ImmutableList.Create<int>(1, 2, 3, 4);

        // 无法直接修改列表内容
        // immutableList.Add(5); // 编译错误

        // 新增或移除元素会创建一个新列表
        var newList = immutableList.Add(5);
        Console.WriteLine(string.Join(", ", newList)); // 输出: 1, 2, 3, 4, 5
    }
}

特点

  • 不可变集合创建后不能直接修改。
  • 修改操作会返回一个新的不可变集合。
  • 保证线程安全。

2. 使用 ReadOnlyCollection<T>

ReadOnlyCollection<T> 是一个包装器,提供只读视图的集合。

示例代码
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

class Program
{
    static void Main()
    {
        var list = new List<int> { 1, 2, 3, 4 };

        // 创建只读集合
        var readOnlyList = new ReadOnlyCollection<int>(list);

        // readOnlyList[0] = 10; // 编译错误:只读集合不能被修改

        Console.WriteLine(string.Join(", ", readOnlyList)); // 输出: 1, 2, 3, 4
    }
}

特点

  • 对底层集合的更改会影响到 ReadOnlyCollection<T>
  • 若需要真正不可变的列表,则应禁止对底层集合的修改。

3. 返回只读接口 IReadOnlyList<T>

使用 IReadOnlyList<T> 接口创建只读访问的集合。

示例代码
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var list = new List<int> { 1, 2, 3, 4 };

        // 返回只读接口
        IReadOnlyList<int> readOnlyList = list;

        // readOnlyList[0] = 10; // 编译错误:只读接口不能被修改

        Console.WriteLine(string.Join(", ", readOnlyList)); // 输出: 1, 2, 3, 4
    }
}

特点

  • 提供只读接口,防止通过此接口修改集合。
  • 底层集合可变,因此需要避免直接操作原集合。

4. 使用自定义封装实现真正不可变 List

通过封装类隐藏修改方法,确保列表不可变。

示例代码
using System;
using System.Collections.Generic;

class ImmutableList<T>
{
    private readonly List<T> _list;

    public ImmutableList(IEnumerable<T> items)
    {
        _list = new List<T>(items);
    }

    public T this[int index] => _list[index];

    public int Count => _list.Count;

    public IEnumerable<T> Items => _list.AsReadOnly();

    // 不提供 Add、Remove 等修改方法
}

class Program
{
    static void Main()
    {
        var immutableList = new ImmutableList<int>(new[] { 1, 2, 3, 4 });

        Console.WriteLine(string.Join(", ", immutableList.Items)); // 输出: 1, 2, 3, 4
    }
}

特点

  • 确保底层集合不会被修改。
  • 可自定义扩展和控制逻辑。

5. 通过返回副本来避免修改

将操作封装成返回新列表的模式。

示例代码
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var list = new List<int> { 1, 2, 3, 4 };

        // 创建副本
        var immutableList = new List<int>(list);

        // 不直接暴露原始列表
        Console.WriteLine(string.Join(", ", immutableList)); // 输出: 1, 2, 3, 4
    }
}

特点

  • 每次操作都基于副本,避免直接修改。
  • 开销可能较高。

总结

  • 推荐方法: 使用 ImmutableList<T>,因其线程安全且性能优化。
  • 简单需求: 使用 ReadOnlyCollection<T>IReadOnlyList<T> 提供只读访问。
  • 完全控制: 自定义封装类实现不可变逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

面试八股文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值