如何在 C# 中使用只读的 Collections

DotNetCore实战

共 6184字,需浏览 13分钟

 · 2021-03-25


集合 表示一组可用于获取和存储的对象,在 C# 中提供了两种类型的集合。

  • 普通集合
  • 泛型集合

前者存在于 System.Collections 命名空间下,属类型不安全的,后者存在于 System.Collections.Generic 命名空间下,属类型安全的。

不可变对象 定义为一旦创建就不可变更的对象, 在 .NET Core 中就存在着这三大 IReadOnlyList,IReadOnlyDictionary 和 IReadOnlyCollection 不可变集合,这篇文章我们就来讨论这些不可变集合以及在C#中如何使用。

三大只读类型介绍

IReadOnlyCollection 表示一个只读集合的基础接口,它实现了 IEnumerable 接口,代码定义如下:


    public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable
    {
        int Count { get; }
    }

IReadOnlyDictionary 表示一个字典的只读形态,它实现了基础的只读集合接口 IReadOnlyCollection, 下面的代码展示了如何将 泛型字典 只读化。


public IReadOnlyDictionary<stringstring> Dictionary { get; } = new Dictionary<stringstring>
        {
            { "1""ABC" },
            { "2""XYZ" },
            { "3""PQR" },
        };

IReadOnlyList 表示一个列表的只读形态,值得注意的是 只读集合 只能通过 index 访问,如下代码所示:


    [DefaultMember("Item")]
    public interface IReadOnlyList<out T> : IEnumerable<T>, IEnumerableIReadOnlyCollection<T>
    {
        T this[int index] { get; }
    }

使用 IReadOnlyList 替换 List

接下来我们看一下如何使用 IReadOnlyList 替换 List 来实现列表的只读化,考虑下面的类。


public class Author
{
   public int Id { getset; }
   public string FirstName { getset; }
   public string LastName { getset; }
}

假如你想从数据库中返回 author 集合,使用如下代码:


public static List<Author> GetAuthors()
{
   return new List<Author>
   {
       new Author
       {
           Id = 1,
           FirstName = "Joydip",
           LastName = "Kanjilal"
       },
       new Author
       {
           Id = 2,
           FirstName = "Steve",
           LastName = "Smith"
       }
    };
}

为了简化,我省略了对数据库繁琐的操作,下面的代码展示了如何在 Main 方法中调用 GetAuthors() 方法。


static void Main(string[] args)
{
    var authors = GetAuthors();
    Console.Read();           
}

显而易见上面的这种 authors 集合是我们用的最多的可变集合,那现在的问题是如何阻止 authors 被修改呢?这里就可以使用 IReadOnlyList 来确保 GetAuthors() 方法返回的集合不可更变,做法就是将方法的返回值从 List<Author> 修改为 IReadOnlyList<Author>,如下代码所示。


public static IReadOnlyList<Author> GetAuthors()
{
   return new List<Author>
   {
      new Author
      {
          Id = 1,
          FirstName = "Joydip",
          LastName = "Kanjilal"
      },
      new Author
      {
          Id = 2,
          FirstName = "Steve",
          LastName = "Smith"
      }
    };
}

接下来看一下 Main 下的 authors 是否有可添加的 Add() 方法?如下图所示:

使用 IEnumberable 接口

不知道大家可否发现,现存的只读接口都继承了 IEnumberable,这就意味着 IEnumberable 也是一种只读形态,如果你只需要对集合进行迭代,那么就可以使用 IEnumberable 接口啦,如下代码所示:


public void MyMethod(IEnumerable<Author> authors)
{
  foreach (Author author in authors)
  {
      //Write your code here
  }
}

如果需求不满足,可以对 IEnumerable 继续向下转型,比如想对集合进行索引访问,那么可以转成 IReadOnlyList 接口,尽量满足 可用功能的最小化 ,改造后的代码如下:


public void MyMethod(IReadOnlyList<Author> authors)
{
  int count = authors.Count;
  for(int index = 0; index < count; index++)
  {
      var author = authors[index];
      //Write your code here
  }
}

IEnumerable 是 .NET 较早版本可用于只读集合形态的接口, 在 .NET Core 中提供了新的只读接口可用于阻止集合的修改,不过值得注意的是,这些对数据提供只读视图的接口,本质上来说也仅仅是高层的封装而已。

译文链接:https://www.infoworld.com/article/3610473/how-to-work-with-read-only-collections-in-csharp.html



往期精彩回顾




【推荐】.NET Core开发实战视频课程 ★★★

.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划

【.NET Core微服务实战-统一身份认证】开篇及目录索引

Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南)

.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

10个小技巧助您写出高性能的ASP.NET Core代码

用abp vNext快速开发Quartz.NET定时任务管理界面

在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度

现身说法:实际业务出发分析百亿数据量下的多表查询优化

关于C#异步编程你应该了解的几点建议

C#异步编程看这篇就够了


浏览 40
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报