You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Razor视图中两个独立Batch列表被意外修改?

问题

我通过页面模型在Razor视图中创建了两个独立的Batch列表:

@model IEnumerable<Batch>
@{
    ViewBag.Title = "Batches";
    bool FirstEveningBatch = true;
    List<Batch> WeekDaysBatch = new List<Batch>(Model.ToList());
    List<Batch> WeekEndBatch = new List<Batch>(Model.ToList());
}

随后调用第一个列表的扩展方法:

@foreach (var item in WeekDaysBatch.Where(x => !x.IsWeekendBatch).AppendBatchNumber())
{
    // ... some code ...
}

AppendBatchNumber扩展方法代码:

public static IEnumerable<Batch> AppendBatchNumber(this IEnumerable<Batch> batches)
{
    bool IsFirstEveningBatch = true;
    int batchnumber = 0;

    Batch[] batchesArray = batches.OrderBy(x=> x.StartTime).ToArray();

    for (int i = 0; i < batchesArray.Length; i++)
    {
        if (batchesArray[i].Name.StartsWith("Evening") && IsFirstEveningBatch)
        {
            batchnumber = 0;
            IsFirstEveningBatch = false;
        }

        batchesArray[i].Name = string.Format("{0}-{1}", batchesArray[i].Name, ++batchnumber);
    }

    return batchesArray;
}

但第二个列表WeekEndBatch也被修改了,请问如何避免这种情况?

Batch类定义:

public class Batch
{
    public int Id { get; set; }
    public string Name { get; set; }

    [NoBatchAfter9PM]
    public TimeSpan StartTime { get; set; }

    [NoBatchAfter9PM]
    public TimeSpan EndTime { get; set; }

    public string? Description { get; set; }

    [Display(Name="Is it a Weekend batch?")]
    public bool IsWeekendBatch { get; set; }

    [Display(Name = "Is it a Women's batch?")]
    public bool IsWomenBatch { get; set; }

    public ICollection<Learner>? Learners { get; set; }
    public Coach? Coach { get; set; }
}
解决方案

问题根源

你创建的两个列表虽然是独立的集合容器,但它们存储的是同一个Batch对象的引用。当扩展方法修改batchesArray[i].Name时,实际是直接修改了原对象的属性值,所有持有该对象引用的列表都会同步看到变化。

具体解决办法

1. 创建Batch对象的独立副本

在初始化两个列表时,不要直接复制对象引用,而是为每个Batch创建新实例:

List<Batch> WeekDaysBatch = Model.Select(b => new Batch
{
    Id = b.Id,
    Name = b.Name,
    StartTime = b.StartTime,
    EndTime = b.EndTime,
    Description = b.Description,
    IsWeekendBatch = b.IsWeekendBatch,
    IsWomenBatch = b.IsWomenBatch,
    // 如果Learners和Coach不需要完全独立,可直接引用;否则需递归拷贝
    Learners = b.Learners?.ToList(),
    Coach = b.Coach
}).ToList();

List<Batch> WeekEndBatch = Model.Select(b => new Batch
{
    Id = b.Id,
    Name = b.Name,
    StartTime = b.StartTime,
    EndTime = b.EndTime,
    Description = b.Description,
    IsWeekendBatch = b.IsWeekendBatch,
    IsWomenBatch = b.IsWomenBatch,
    Learners = b.Learners?.ToList(),
    Coach = b.Coach
}).ToList();

2. 修改扩展方法,不修改原对象

调整AppendBatchNumber方法,返回新的Batch实例而非修改原对象:

public static IEnumerable<Batch> AppendBatchNumber(this IEnumerable<Batch> batches)
{
    bool IsFirstEveningBatch = true;
    int batchnumber = 0;

    var orderedBatches = batches.OrderBy(x => x.StartTime);

    foreach (var batch in orderedBatches)
    {
        if (batch.Name.StartsWith("Evening") && IsFirstEveningBatch)
        {
            batchnumber = 0;
            IsFirstEveningBatch = false;
        }

        // 返回新实例,原对象不受影响
        yield return new Batch
        {
            Id = batch.Id,
            Name = string.Format("{0}-{1}", batch.Name, ++batchnumber),
            StartTime = batch.StartTime,
            EndTime = batch.EndTime,
            Description = batch.Description,
            IsWeekendBatch = batch.IsWeekendBatch,
            IsWomenBatch = batch.IsWomenBatch,
            Learners = batch.Learners,
            Coach = batch.Coach
        };
    }
}

3. 为Batch类添加克隆方法

在Batch类中实现克隆逻辑,方便复用:

public class Batch
{
    // 原有属性...

    public Batch Clone()
    {
        return new Batch
        {
            Id = this.Id,
            Name = this.Name,
            StartTime = this.StartTime,
            EndTime = this.EndTime,
            Description = this.Description,
            IsWeekendBatch = this.IsWeekendBatch,
            IsWomenBatch = this.IsWomenBatch,
            Learners = this.Learners?.ToList(),
            Coach = this.Coach // 若Coach是引用类型,需同步实现Clone方法
        };
    }
}

之后创建列表时直接调用克隆方法:

List<Batch> WeekDaysBatch = Model.Select(b => b.Clone()).ToList();
List<Batch> WeekEndBatch = Model.Select(b => b.Clone()).ToList();

内容的提问来源于stack exchange,提问作者Sagar Tube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:54:52