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 をレベル タイプで並べ替え、次にレベル値で並べ替えて、並べ替えられたリストを返しています。

私のプログラムの1つに、次のコードがあります。

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 メソッドはそうではありません。エラーが発生しません。

以前は、RouteMatrix はパブリック フィールドでした。この問題は、プライベートにしてパブリック プロパティにカプセル化した後に発生し始めました。

4

3 に答える 3

2

申請するToList()と、元のリストとは関係のない、まったく新しいリストが作成され_routeMatrixます。まあ、それらは同じ要素を共有しますが、リストの 1 つから要素を追加または削除しても、2 番目のリストには影響しません。

MSDNから:

クエリ結果のキャッシュされたコピーを取得するために、このメソッドをクエリに追加できます。

したがって、正常に変更しているコピーをキャッシュしました。_routeMatrix


この問題を解決するには、 IListの代わりにIEnumerableを返し(推定クラス外でのコレクションの変更を無効にするため)、ルート情報を に追加する推定クラスへのメソッドを作成します。そのメソッドを使用して、新しいアイテムを追加します。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()

ここでの教訓は、ゲッターを複雑にしすぎないことだと思います。Add() だけが必要な場合は、とにかく並べ替えは無駄な労力です。

また、悪いことが起こるのは_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 に答える