为什么修改一个会话变量还会修改另一个会话变量?

时间:2019-06-26 20:16:02

标签: c# asp.net

我有一个奇怪的问题。我的变量之一通过此函数更改(下面的代码)。我不知道怎么可能。我想更改Session["p_skok"],但是在某种程度上,变量Session["z_skok"]也正在更改。

    protected void oblicz_parametry()
    {
        List<string> lista_odnosnik_wartosc = (List<string>)Session["p_wartosc"];
        List<Type> lista_odnosnik_typ = (List<Type>)Session["p_typ"];
        List<bool> lista_odnosnik_inkrementacja = (List<bool>)Session["p_inkrementacja"];
        List<int> lista_odnosnik_nr = (List<int>)Session["p_nr"];
        List<int> lista_odnosnik_skok = (List<int>)Session["p_skok"];

        List<int> lista_odnosnik_skok_pomocnicza = (List<int>)Session["z_skok"];
        if (Session["iteracja"] != null)
        {
            for (int i = 0; i < lista_odnosnik_inkrementacja.Count(); i++)
            {
                if (lista_odnosnik_skok[i] == 0 && lista_odnosnik_inkrementacja[i] == true)
                {
                    int zwieksz = lista_odnosnik_nr[i];
                    //if (lista_odnosnik_typ[i].ToString() == "int")
                    //{
                        int zm_pomocnicza = Convert.ToInt32(lista_odnosnik_wartosc[i]) + lista_odnosnik_nr[i];
                        lista_odnosnik_wartosc[i] = zm_pomocnicza.ToString();
                    //}
                    lista_odnosnik_skok[i] = lista_odnosnik_skok_pomocnicza[i] + 1;
                }
                lista_odnosnik_skok[i]--;
            }
            Session["p_wartosc"] = lista_odnosnik_wartosc;
            Session["p_skok"] = lista_odnosnik_skok;

        }
        else
        {
            Session["iteracja"] = 1;
            Session["p_wartosc"] = Session["z_wartosc"];
            Session["p_inkrementacja"] = Session["z_inkrementacja"];
            Session["p_nr"] = Session["z_nr"];
            Session["p_skok"] = Session["z_skok"];

            oblicz_parametry();

        }
    }

我进行了一些调试,发现减少的原因是代码的lista_odnosnik_skok[i]--;部分。你知道会发生什么吗?

2 个答案:

答案 0 :(得分:2)

在程序生命周期的某个时刻,您将这两个会话变量设置为等效:

Session["p_skok"] = Session["z_skok"];

此行代码位于else块中。该会话将持续很长时间,甚至可能长达几个小时:


enter image description here


这行代码运行之后,它们都将引用内存中的同一列表对象,并且对Session["p_skok"]lista_odnosnik_skokSession["z_skok"];或{ {1}}都将具有相同的效果,因为它们都是对同一lista_odnosnik_skok_pomocnicza

的引用

答案 1 :(得分:2)

这是两件事的结合。在else子句中,您可以这样:

Session["p_skok"] = Session["z_skok"];

一旦执行此操作,这两个变量将引用同一列表。现在,无论您对一个列表执行什么操作,您都对另一个列表执行操作,因为它们是相同的列表。

然后您要设置Session["iteracja"] = 1;,这意味着下一次条件if (Session["iteracja"] != null)将为真。

在这种情况下,您将更改lista_odnosnik_skok,即Session["p_skok"],它与Session["z_skok"];相同。


要解决此问题,请不要将一个会话变量设置为等于另一个。您可以这样做:

var existingList = (List<int>)Session["z_skok"];
Session["p_skok"] = new List<int>(existingList);

现在,您已经创建了一个新列表,其中包含与原始列表相同的元素。它们是两个不同的列表,因此修改一个列表不会修改另一个列表。

值得注意的是,这是有效的,因为int是一种值类型,而不是引用类型,因此,当您将一个列表中的值添加到另一个列表中时,便会创建新值。您可以修改一个列表中的值,而无需修改其他列表。

如果列表中的项目是引用类型,您仍然会遇到类似的问题。您将有两个列表(好),但它们都将包含对相同对象的引用(可能不好)。您可以在一个列表上添加或删除,而无需修改其他列表,但是修改列表中的项目将修改另一个列表中的项目,因为它们都是同一项目。

但是,这仅是一个解释。该列表包含int,因此在这种情况下这不是问题。


如果您从Session开始将所需的所有内容读入变量,然后将所有内容保存回Session,则可能更容易理解。这样,您就不会试图同时跟踪局部变量和会话变量。令人困惑,这意味着更容易犯错误。

您甚至可能会发现定义一个包含所有这些列表的新类很有帮助。从会话中检索一个对象(如果为空,则创建一个新对象),并在完成使用后保存整个对象。与您的操作相同,但是现在您只需要处理一个会话变量,而不是五个,并且更容易进行跟踪。