1

我有一个名为 Estimate 的类,它具有以下字段和属性:

private IList<RouteInformation> _routeMatrix;
public virtual IList<RouteInformation> RouteMatrix
{
    get
    {
        if (_routeMatrix != null && _routeMatrix.Count > 0)
        {
            var routeMatrix = _routeMatrix.ToList();
            routeMatrix =
                    routeMatrix.OrderBy(tm => tm.Level.LevelType).ThenBy(tm => tm.Level.LevelValue).ToList();
            return routeMatrix;
        }
        else return _routeMatrix;
    }
    set { _routeMatrix = value; }
}

因此,在 getter 方法中,我只是按级别类型和级别值对 _routeMatrix 进行排序,然后返回排序后的列表。

在我的一个程序中,我有以下代码:

public void SaveApprovers(string[] approvers)
{
    int i = 1;
    foreach (var approver in approvers)
    {
        var role = Repository.Get<Role>(long.Parse(approver));
        var level = new Models.Level
        {
            LevelType = LevelType.Approver,
            LevelValue = (LevelValue)i,
            Role = role
        };
        Repository.Save(level);
        var routeInformation = new Models.RouteInformation
        {
            Level = level,
            RouteObjectType = RouteObjectType.Estimate,
            RouteObjectId = _estimate.Id
        };
        Repository.Save(routeInformation);
        _estimate.RouteMatrix.Add(routeInformation); // <--- The problem is here
        Repository.Save(_estimate);
        i++;
    }
}

问题是,如果有多个批准者(即:approvers数组的长度大于 1,则只routeInformation添加第一个RouteMatrix。我不知道其余的会发生什么,但 Add 方法不会t给出任何错误。

早些时候,RouteMatrix 是一个公共字段。在我将其设为私有并将其封装在公共属性中后,此问题开始出现。

4

3 回答 3

2

当您申请时ToList(),会创建与原始列表无关的全新_routeMatrix列表。好吧,它们共享相同的元素,但是当您从其中一个列表中添加或删除元素时,它不会影响第二个列表。

来自MSDN

您可以将此方法附加到查询中,以获取查询结果的缓存副本。

因此,您已经缓存了您成功修改的副本。_routeMatrix


要解决此问题,您可以返回IEnumerable而不是IList(以禁用估计类之外的集合修改),并AddRouteInformation为估计类创建方法,该方法将向_routeMatrix. 使用该方法添加新项目:

_estimate.AddRouteInformation(routeInformation);
Repository.Save(_estimate);
于 2013-07-19T12:22:18.020 回答
2

您的get成员返回一个不同的列表,您将其添加到该临时列表中。

 get
 {
    if (_routeMatrix != null && _routeMatrix.Count > 0)
    {
        var routeMatrix = _routeMatrix.ToList(); // ToList creates a _copy_ of the list
        ...
        return routeMatrix;
    }
    else return _routeMatrix;
 }

 .....

 _estimate.RouteMatrix.Add(routeInformation);   // add to the result of ToList()

我认为这里的道德是不要让吸气剂太复杂。当您只想添加()时,无论如何排序都是浪费精力。

此外,当_routeMatrix == null. 这可能不会发生,但那if (_routeMatrix != null && ...)部分是误导性的噪音。

于 2013-07-19T12:22:39.323 回答
1

问题是您实际上并没有修改_routeMatrix,您正在修改它的副本。不要发出ToListon _routeMatrix,只需对其进行排序。更改get为:

get
{
    if (_routeMatrix != null && _routeMatrix.Count > 0)
    {
        _routeMatrix =
                _routeMatrix.OrderBy(tm => tm.Level.LevelType).ThenBy(tm => tm.Level.LevelValue).ToList();
        return _routeMatrix;
    }
    else return _routeMatrix;
}
于 2013-07-19T12:25:09.577 回答