在c#中修改对象

本文关键字:对象 修改 | 更新日期: 2023-09-27 18:11:47

(如果你能想到更好的标题,请告诉我)

我正在做一个路线优化程序。我从这条路线需要包括的点列表开始。我的第一步是创建一个包含所有可能路径(排列)的列表。然后,我可以删除任何路线(例如,如果一个站点必须先于另一个站点)。一旦完成,我计算每个点之间的距离和时间,在每条可能的路线上。每个点都是一个对象(TPoint),所有的距离和时间值都存储在一个名为TData的单独类中,该类存储在TPoint的每个实例中。我的问题是:当我尝试更新TData时,比如说,在第一站,在第一条可能的路线中,它将更新每个可能路线中相同TPoint的TData。这是因为类是一个引用类型,并且存储在堆上。我正在寻找一个解决方案,允许我在每个TPoint上存储TData。

下面是一些示例代码(下面的代码演示了当我修改一个对象(TPoint)时,我实际上只是使用引用来修改堆上的对象):

主要

// Let's create a list of points we need to hit.
List<TPoint> lstInitial = new List<TPoint>();
lstInitial.Add(new TPoint("A", new TData(-1, -1)));
lstInitial.Add(new TPoint("B", new TData(-1, -1)));
lstInitial.Add(new TPoint("C", new TData(-1, -1)));
// Now let's get all possible routes
IList<IList<TPoint>> lstPermutations = Permutations(lstInitial);
// Let's write these values to the first point, in the first possible route.
lstPermutations[0][0].oTData.distance = 10;
lstPermutations[0][0].oTData.minutes = 20;
foreach (IList<TPoint> perm in lstPermutations)
{
    foreach (TPoint p in perm)
    {
        Response.Write(p.id + "|" + p.oTData.distance + "|" + p.oTData.minutes);
        Response.Write(" ");
    }
    Response.Write("<br />");
}
<<p> 排列功能/strong>
// Get permutations
private static IList<IList<T>> Permutations<T>(IList<T> list)
{
    List<IList<T>> perms = new List<IList<T>>();
    // If the list is empty, return an empty list.
    if (list.Count == 0)
    {
        return perms;
    }
    // This is a loop method to get the factorial of an integer
    int factorial = 1;
    for (int i = 2; i <= list.Count; i++)
    {
        // shortcut for: factorial = factorial * i;
        factorial *= i;
    }
    for (int v = 0; v < factorial; v++)
    {
        //List<T> s = new List<T>(list);
        List<T> s = new List<T>(list);
        int k = v;
        for (int j = 2; j <= list.Count; j++)
        {
            int other = (k % j);
            T temp = s[j - 1];
            s[j - 1] = s[other];
            s[other] = temp;
            k = k / j;
        }
        perms.Add(s);
    }
    return perms;
}

public class TPoint
{
    public TPoint(string _id, TData _oTData)
    {
        id = _id;
        oTData = _oTData;
    }
    public string id { get; set; }
    public int someInt { get; set; }
    public TData oTData { get; set; }
}
public class TData
{
    public TData(int _distance, int _minutes)
    {
        distance = _distance;
        minutes = _minutes;
    }
    public int distance { get; set; }
    public int minutes { get; set; }
}

看起来好像我把自己逼到了一个角落里。我可以想到一些解决方案,但它们看起来很乱,所以我想我应该问一下专家。

编辑

有人能想到为什么这不是一个好主意吗?

而不是这样,这会修改堆上的对象(并影响每个可能路由中的每个点):

lstPermutations[0][0].oTData.distance = 10;
lstPermutations[0][0].oTData.minutes = 20;

使用this,它只创建一个类的新实例:

TPoint oTPoint = new TPoint(lstPermutations[0][0].id, new TData(10, 20));
lstPermutations[0][0] = oTPoint;

在c#中修改对象

如果你让TData成为一个结构体,那么它将被按值复制而不是按引用复制。否则,您将不得不创建一个复制值的浅克隆。

为什么不通过删除set访问器来使简单的TData类型不可变,这样通过值复制或通过引用复制都不会有太大的影响。它在功能上可能相当于Tuple<int, int>

对象是存储在堆上还是存储在其他地方可能并不重要。如果您决定使对象不可变,那么将其设置为struct是很自然的,但是class也很好。