【问题标题】:Unable to modify the properties of objects within an IEnumerable<T>无法修改 IEnumerable<T> 中对象的属性
【发布时间】:2011-05-17 22:46:01
【问题描述】:

我在更改 IEnumerable 集合中对象的属性时遇到问题。我将集合传递给另一种方法,以删除集合中实体之间的重复信息。这在方法中有效,但是一旦方法执行完毕并返回给调用者,更改就会丢失。但是,如果我将 IEnumerable 转换为列表,它会按预期工作。我唯一的猜测是,因为当我调用 ToList 时,它变成了一个具体类型并且允许它工作,但这不应该是一个限制,对吧?

此外,这不在延迟执行的上下文中,这毫无价值。 这最终不是真的,编译器正在重写 RetrieveTrackingFilters 方法以利用延迟执行

这是精简后的代码:

public IEnumerable<TrackingFilter> RetrieveTrackingFilters(string proNumber)
{
    var trackingFilters = new EntityCollection<TrackingOverviewFilterEntity>(new TrackingOverviewFilterEntityFactory());

    var filter = new RelationPredicateBucket();
    filter.Relations.Add(TrackingOverviewFilterEntity.Relations.TrackingOverviewEntityUsingTrackingOverviewId);
    filter.PredicateExpression.Add(TrackingOverviewFields.ProNumber == proNumber);

    DataAccessAdapterFactory.Instance().FetchEntityCollection(trackingFilters, filter);

    return BuildTrackingFilterColl(trackingFilters); //Just news up a DTO object and populates it
}

public TrackingSummaryViewModel RetrieveTrackingSummary(string proNumber)
{
    ...
    var trackingFilters = this._TrackingOverviewDataController.RetrieveTrackingFilters(proNumber).ToList(); //Works
    //var trackingFilters = this._TrackingOverviewDataController.RetrieveTrackingFilters(proNumber); //Doesn't work

    RemoveDuplicateFilterData(trackingFilters); //If I don't do a ToList() then the changes that occur in this method call do not persist
    ...
}

private static void RemoveDuplicateFilterData(IEnumerable<TrackingFilter> filters)
{
    var valuePairs = new Dictionary<string, IList<object>>();

    foreach (var filter in filters)
    {
        if (valuePairs.ContainsKey("comments") && valuePairs["comments"].Contains(filter.Comments))
        {
            filter.Comments = string.Empty;
        }
        else if (!string.IsNullOrWhiteSpace(filter.Comments))
        {
            if (!valuePairs.ContainsKey("comments"))
            {
                valuePairs.Add("comments", new List<object>());
            }

            valuePairs["comments"].Add(filter.Comments);
        }    
    }

    ...
}

【问题讨论】:

  • .ToList() 不是对列表的强制转换,它是一种扩展方法,它使用来自 IEnumerable 的值创建一个新列表。结果不是将旧结构转换为列表,而是与旧结构具有相同元素的新结构。
  • @albin sunnanbo,对不起,你是对的,我用错了措辞。其实我早就知道了。
  • 你的类型实际上是一个结构体吗?

标签: .net c#-4.0


【解决方案1】:

如果您的RetrieveTrackingFilters(proNumber) 返回一个IQueryable,那么这将导致每次您枚举它时都会创建新对象:一次在RemoveDuplicateFilterData 中(那里的更改将会丢失),一次当您使用稍后在RetrieveTrackingSummary 中发布(此时将提供一个新的、未改动的副本)。

尝试将.ToList() 更改为.AsEnumerable()。它应该仍然可以正常工作。

【讨论】:

  • 我的代码粘贴中的第一个方法是 RetrieveTrackingFilters,它返回一个 IEnumerable
  • @joshlrogers,IQueryable 实现了 IEnumerable,因此 IQueryable 可以“隐藏”在 IEnumerable 中。
  • @joshlrogers,在调试器中检查运行时类型
  • 好的,返回类型是:System.Linq.Enumerable.WhereSelectEnumerableIterator 这意味着编译器正在重写我的第一个方法来实际执行延迟执行。所以我必须执行 ToList() 才能执行查询。好吧,谢谢你带领我朝着正确的方向前进。我会将您的回复标记为答案
猜你喜欢
  • 2020-04-20
  • 1970-01-01
  • 2013-05-17
  • 1970-01-01
  • 2014-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多