今天在开发中遇到了这个问题
ArrayList list = (ArrayList)Session["FormControl"]
修改list里面的对象的值,Session里面的值也会跟着改变。接着我有进行了几个试验,发现只要Session里存储的是引用类型,修改对象的值,Session里面的值也会改变,如果存储值类型的就不会改变,如果存储的是string类型的话也不会改变! 我想问的是Session是怎么存储数据的,是存储的地址,还是别的?上面这个情况发生的原因是什么?希望各位能帮我解答这个问题,越透彻越好!!!

解决方案 »

  1.   

    这个理解应该不难吧???个人感觉Session类似于于OBJECT```````
      

  2.   

    Session
    存什么都可以
    由于你存的就是引用类型
    在C#里对象除了值类型
    就是引用类型
    String有点特殊的引用类型
      

  3.   

    那就是说如果存的是引用类型的话,从Session里取出来的只是一个引用,他们还指向同一块内存空间?
    但是String也是引用类型,却没有这种情况,如果是特殊的引用类型,那它还有什么其它特殊的情况啊?
      

  4.   

    string给让大家觉得是值类型的原因是你以为string的赋值是修改其成员,其实不是,相当于一个new的过程,还是改变了引用的地址
      

  5.   

    session的工作原理:当用户请求一个asp.net页面时,系统将自动创建一个session会话,退出应用程序或关闭服务器时该会话撤消.系统在创建会话时将为其分配一个长的字符串(SessionID)标识,以实现对话进行管理和跟踪.该字符串只包含URL中所允许的ASCII字符.SessionID具有的随机性和唯一性保证了会话不会冲突,也不被会怀有恶意的人利用新SessionID推算出现有会话的SessionID推算出现有会话的SessionID.
    通常情况下,SessionID会存放在客户端的Cookies内,当用户访问asp.net网站中的任何页面时,SessionID将通过Cookies传递到服务器端,服务器根据SessionID的值对用户进行识别,以返回对应该用户的Session信息.通过配置应用程序,可以在客户端不支持Cookies时将SessionID嵌套在URL中,服务器可以通过请求的URL获得SessionID值.
    Session信息可以存放在asp.net进程,状态服务器或SQL Server数据库当中.默认的情况下Session的生存周期为20min,可以通过Session的Timeout属性更改这一设置.在Session的生存周期内Session是有效的,超过了这个时间Session就会过期,Session对象将被释放,其中存储的信息也将丢失.
      

  6.   


    按你说的,string在Session里存储的是值
    string str = Session["str"].ToString()相当于重新new了一块内存地址,
    所以修改str的值不会改变Session的值
    但是如果我们这样
    ArrayList list = new ArrayList();
    list = (ArrayList)Session["FormControl"];
    修改list时还是会改变Session内的值,这应该说面Session内存储的是其引用,
    list = (ArrayList)Session["FormControl"]只是将其引用付给了list,他们都还指向同一块内存空间,所以一个被改动另一个也会变化,
    但是同为引用类型的String却不一样。
    如果就此认为String在Session存储上是个特殊的情况的话,我认为有点小瞧微软了。
    我的理解是Session存储的是引用类型类型时,存储的是其引用,而存储值类型的时候存储的是其值,并没有针对String进行特殊处理,
    造成String特殊的应该是在string str = Session["str"].ToString()这句,
    说明所有对字符串进行赋值操作的语句,不仅仅是new了一个新的内存空间,更重要的是它采用的是拷贝构造(深拷贝),而非其它类的构造函数以上是我翻阅资料理解的,如果大家有什么更好说明这个现象的资料请告诉我!谢谢
      

  7.   

    非也:    protected void Button1_Click(object sender, EventArgs e)
        {
            //填充
            Class1 c = new Class1();
            c._a = "1111111111";
            Session["a"] = c;
        }
        protected void Button2_Click(object sender, EventArgs e)
        {
            //修改
            Class1 c = new Class1();
            c._a = "2222222222";
        }
        protected void Button3_Click(object sender, EventArgs e)
        {
            //打印
            Class1 c = (Class1)Session["a"];
            Response.Write(c._a);    }
    多试几次, session 的值 并没有改变 。
      

  8.   

    这是跟Session没关系的问题.完全是类似:
    class Test 
    {
      public  string TestString { get; set; }
    }
      Test t = new Test { TestString = "abc" };
    00000031  mov         ecx,54A277Ch 
    00000036  call        FB930914 
    0000003b  mov         esi,eax 
    0000003d  mov         ecx,esi 
    0000003f  call        FED0B080 
    00000044  mov         edi,esi 
    00000046  mov         edx,dword ptr ds:[024131C4h] 
    0000004c  mov         ecx,edi 
    0000004e  cmp         dword ptr [ecx],ecx 
    00000050  call        FED0B070 
    00000055  nop              
    00000056  mov         dword ptr [ebp-44h],edi 
            Test t1 = t;
    00000059  mov         ebx,dword ptr [ebp-44h] 
            t1.TestString = "ccc";
    0000005c  mov         edx,dword ptr ds:[024131DCh] 
    00000062  mov         ecx,ebx 
    00000064  cmp         dword ptr [ecx],ecx 
    00000066  call        FED0B070 
    0000006b  nop   和
           String s = "abc";
    0000002c  mov         eax,dword ptr ds:[024131C4h] 
    00000032  mov         esi,eax 

            String s1 = s;
    00000034  mov         edi,esi 
            s1 = "ccc";
    00000036  mov         eax,dword ptr ds:[024131DCh] 
    0000003c  mov         edi,eax 
    的问题
      

  9.   


    个人 觉得 SEssion  是和 cookie 一个类型的,并不是 随意就可以改变值的。
      

  10.   

    LZ估计是你的代码存在问题。说到STRING ,当你NEW 一个的时候,分配固定的空间,之后如果对其进行更改,将不会在原地址更改,而时另外NEW了一块空间存放,这也是MS又出了 STRINGBUILDER 的原因。 LZ可以查阅MSDN获得更详细的说明
      

  11.   

    修改成这样就会出现这种情况了protected void Button2_Click(object sender, EventArgs e) 

        //修改 
        Class1 c = (Class1)Session["a"]; 
       c._a = "2222222222"; 
      

  12.   

    应该存放的是对象的引用,至于string比较特殊(string的值无法改变)
      

  13.   

    protected void Button2_Click(object sender, EventArgs e) 

        //修改 
        Class1 c = (Class1)Session["a"]; 
       c._a = "2222222222"; 

    这样能修改!
      

  14.   

    我测试了一下.呵呵..public partial class WebForm2 : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                    testClass t = new testClass("a1");                Session["test"] = t;
                    Response.Write("初始化:" + t.A);//输出 初始化:a1
                    Response.Write("<br/>");                if (Session["test"] != null)
                    {
                        testClass t2 = (testClass)Session["test"];                    t2.A = "change";
                        Response.Write(t2.A);//输出 change
                        Response.Write("<br/>");                    testClass t3 = (testClass)Session["test"];
                        Response.Write(t3.A);//输出 change                }
                        }
        }
        public class testClass
        {
            private string a = string.Empty;
            
            public testClass(string _a)
            {
                a = _a;
            }        public string A
            {
                get
                {
                    return a;
                }
                set
                {
                    a = value;
                }
            }
        }
      

  15.   

    大家可以copy我的代码试一下.
      

  16.   

    这个问题和Session没关系,而且注意string是System.String的别名,它继承于Object,string是一但创建就无法改变值的引用类型。
      

  17.   


    class1 test1 = new class1();
    class1 test2 = new class1();
    test1.a = "123";
    test2 = test1;
    test2.a = "456";
    //这时test1.a已经为"456";
    //这个比较好理解,同理Session也是个对象,所以也会产生这种现象
      

  18.   

    这不是Session的问题,所有引用类型与值类型的性质,对Session如此,对一般的List或Array也如此。你去看看.NET基础书吧。
      

  19.   

    这怎么可能呢,session从来都是被动的. 从来不会去主动改变它的值. 即使是引用类型, 它存到session里也应该是实际的值. 比如 myobject o = new myclass();
    这里o是引用类型, 但它存到session里只应该是序列化后的o的实例
      

  20.   

    我来结贴吧   楼主说的问题是确实存在的  
    当session存储引用类型时,当该引用类型的值改变时,session中存储的值会跟着改变。这是我在项目中发现的。
     protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)  
                {
                   _userDic = new Dictionary<Guid, UserDO>();
                    Session[SessionKey_Users] = _userDic;//此时session值为null
                    InitPageData();//此方法中为成员变量_userDic 赋值            } 
                else
                {
                     _userDic = Session[SessionKey_Users] as Dictionary<Guid, UserDO>;[            }     
            }