偶当时的看法是:由于object是一个类,类的运算符需要定义,它的比较是定义(重载)运算符的问题.但是有一点又说不通了.因为在VS2002里,((object)s == (object)t)是真而在Console输出时((object)s == (object)t)却是假,这就让人琢磨不透里面有什么东东了.

解决方案 »

  1.   

    不会啊!
    我刚刚测试,((object)s == (object)t)为falseif((object)s == (object)t)
    {
    Console.WriteLine((object)s == (object)t); 
    }
      

  2.   

    对于预定义的值类型,如果操作数的值相等,则相等运算符 (==) 返回真,否则,返回假。对于除 string 类型以外的引用类型,如果两个操作数引用相同的对象,则 == 返回真。对于 string 类型,== 将比较字符串的值。
      

  3.   

    谢谢 loulanlouzhu(桃花潭水深千尺,不及阿勇念你情) 的支持.不过,我感觉似乎还有些问题没有理通.女同行还是比男同行心细,这小猪妹看的这样细,偶以前学的时候就没在意.
      

  4.   

    OK,让我们继续.
    监视object类型的时候,这个object类型很有意思,
    试试((object)s)看看.里面就只含了一个值.string "Test"有意思的地方是在
    Console中,输出的结果是false
    而VS的跟踪始终是true
      

  5.   

    我没有安装CLR Debuger,无测试JIT代码是否一致,你能否帮测试一下,贴上来.
      

  6.   

    有意思的地方是在
    Console中,输出的结果是false
    而VS的跟踪始终是true
    -->>我跟踪的时候就是false,所以输出的也是falseCLR Debuger--〉〉这个我没用过!咋用!?
      

  7.   

    唉,我在公网上的machine打拼音,太累了,我只能减少中文的count了.string t = string.Copy(s); 
    t只是copy了s的value, 不是reference.(string)s == (string)t
    比较的是value(object)s == (object)t
    比较的是reference当然是FalseStirng是比较经典的不变模式,C#与Java的设计上差不多, 你可以参看Java中相关String类的sourcecode.
      

  8.   

    我的理解:
    首先必须明确CTS System.String类型是一个引用类型。
    string s = "Test"; 
    给s赋值。s在栈中指向堆中占的一个空间。堆中的值是"Test"
    string t = string.Copy(s);
    给t赋值。t在栈中指向堆中占的一个新空间。堆中的值是"Text"
    (Copy方法创建了新实例)Console.WriteLine(s == t); 
    由于"=="默认没有对string重载,所以比较的是s对象和t对象在堆中的地址。
    此是为falseConsole.WriteLine(((object)s).ToString ()); 
    这里先把s转成object型,再利用object的ToString方法把对象的值转成字符显示出来。Console.WriteLine(((object)s).Equals (((object)t))); 
    这里把s和t转成object之后再进行比较,由于此方法以默认重载,所以在此是比较s和t的值。
    此为TureConsole.WriteLine((string)s == (string)t); 
    把对象转为字符进行比较,但用的是"=="号,虽然没有重载但由于比较的是值,所以
    此为TureConsole.WriteLine((object)s == (object)t); 
    比较引用,肯定不同,因为前面的Copy实际上在2个地方放置了对象。
      

  9.   

    推荐 Mastering Visual C#.NET Jason Price & Mike Gunderloy 著,第九章的内容。
      

  10.   

    因为在VS2002里,((object)s == (object)t)是真是因为什么?
      

  11.   

    针对这个问题:
    偶的问题是.单步跟踪(object)s == (object)t 时候,启动程序从string t = string.Copy(s);一句开始,监视的值就一直为True.而最后一句话中Console的输出却是False. 
    记得我以前在VB里调试程序的时候,总是当某行执行过以后才可以利用调试器看出结果,估计是比较之前返回值为True,为何不在比较以后再查看那一行的结果呢?
    针对这个问题:
    因为在VS2002里,((object)s == (object)t)是真
    请确定“=”没有没重载过,因为“=”被重载后“==”会被自动重载。
    就象“+”被重载后“+=”会被自动重载一样。
      

  12.   

    不好意思上面讲的有点不对,应该是针对这个问题:
    因为在VS2002里,((object)s == (object)t)是真
    请确定Equals, “==”和“!=”没有被重载过。
    并且赋值时确定是以传值的方式赋值,而非传引用。
      

  13.   

    (s==t)不用讨论了,肯定是true,因为是值比较.
    ((string)s==(string)t)和(s==t)也是值比较,为true.
    ((object)s==(object)t)是引用比较,是false.
      

  14.   

    ((object)s == (object)t)是false ,不是true!
      

  15.   

    string虽然是引用类型,但是在实际使用中,是作为值类型来用的!。net内部进行了处理!
      

  16.   

    终于想通了楼主的问题了!
    在跟踪(object)s == (object)t 时候,总是显示true,它和输出的结果是两回事.
    在.net中,string是不能改变的,crl只为同样的string分配一块内存.所以总是显示true,但程序执行到((object)s==(object)t)时两个的句柄不同,输出false.这个问题的关键是(object)s取的是引用句柄,而不是物理地址.
      

  17.   

    举个例子来验证自己的说法
    string[] a=new string[1000000];
    for (int i=0;i<=999999;i++)
    a[i]="abcdefghigklmnopqrstuvwxyz";
    在程序里加以上语句,a[0]和a[1]的引用句柄不同,如果全部单独分配内存的话,算来这个字串要占26M内存,但在任何程序里加上看一下,然后再注释掉看一下,所点内存内乎完全一样,说明从a[0]到a[999999]全是使用的是同一内存地址.但是(object)a[0]==(object)a[1]却是false的.
      

  18.   

    using System;class Test

    static void Main()  
    {  
    object s = "Test";  object t = "Test";  Console.WriteLine(s == t);  
    }
    }
    这个为什么相等呢?
      

  19.   

    同意 zhouqi66(部落)的看法,高!!!!
      

  20.   

    经过亲手验证,终于看到了问题的真相:
    string类型确实是引用类型,当你这样赋值时
    string s="Test";
    string t="Test";
    它确实是指向同一地址,所以:
    ((object)s==(object)t)为True.当
    string s="Test";
    string t="Test1";时
    ((object)s==(object)t)为Flase当string s="Test";
    string t=string.Copy(s); 时,由于Copy明确告诉编译器要复制值,所以为Flase.如果是其他基本类型如int,
    int s=1;
    int t=1;
    ((object)s==(object)t)为Flase
      

  21.   

    昨天偶也试了一下,还是感觉不是很对劲.大家试试这个,猜一下结果.呵呵 
    using System;namespace ConsoleApplication1
    {
    /// <summary>
    /// Class1 的摘要说明。
    /// </summary>
    class Class1
    {
    /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main() 
    {
    string s = "Test";
    string t = string.Copy(s);
    Console.WriteLine(s == t);
    Console.WriteLine(((object)s).ToString ());
    Console.WriteLine(((object)s).GetHashCode());
    Console.WriteLine(((object)t).GetHashCode());
    Console.WriteLine(((object)s).Equals (((object)t)));
    Console.WriteLine((string)s == (string)t);
    Console.WriteLine((object)s == (object)t); t = "Test";
    Console.WriteLine((object)s == (object)t);
    t=t+"d";
    t=t.Substring(0,t.Length-1);
    Console.WriteLine((object)s == (object)t);
    Console.ReadLine();
    } }
    }
      

  22.   

    在这部分代码中:
    t = "Test";
    Console.WriteLine((object)s == (object)t);
    t=t+"d";
    t=t.Substring(0,t.Length-1);
    Console.WriteLine((object)s == (object)t);
    Console.ReadLine();偶感觉 好像是内存分配的问题.不是运算符重载的问题.
    第一部分:
    t = "Test";
    Console.WriteLine((object)s == (object)t);
    返回True
    意料之中,也是意料之外.第二部分
    t=t+"d";
    t=t.Substring(0,t.Length-1);
    Console.WriteLine((object)s == (object)t);
    Console.ReadLine();
    是对字符串操作了之后,重新得值.结果是False
    所以,这次比较应该有关内存地址的比较.
    记不清是不是以前看Begining C# 中好像提过类似的事---关于内存分配
    越试越           汗........
      

  23.   

    老大,看看MS出的一本书叫什么字符串与正则表达式吧.哪里面讲的很明白哟.看了你在第29楼的回复你不汗不行了.呵呵.t = "Test";
    Console.WriteLine((object)s == (object)t);
    返回True这是因为,字符串在处理时,如果没有进行操作,就直接指向那个内存地址值.
    而在
    t=t+"d";
    t=t.Substring(0,t.Length-1);
    Console.WriteLine((object)s == (object)t);
    这里时,
    由于字符串内容发生变化,所以,CLR会重新给t分配一块内存.
    这时再用Console.WriteLine((object)s == (object)t);
    比较时,就是False了,因为它们引用的内存地址不一样.为什么在VS2002监视时,会是True呢?
    其实也很简单.
    是因为,VS2002它在Debug时,对于
    (object)s == (object)t
    中的
    (object)s (或(object)t)
    来说,里面只有一个String "Test"
    也就是说(object)s能让VS2002看到的只有这么一个东西.
    所以比较时,也就返回True了.
    所以.....
    To楼主:对于专家分来说,偶就不要了,偶看见这里全是星星,所以分也没什么意思,就送给我们的杨秘书吧.再多点更好.你这个题目真的不只20分的.呵呵,各位见笑了.
      

  24.   

    刚好昨天和别人讨论时提到“字符串池”的概念,
    回去写了一些程序,查看了IL,果然存在这种现象。楼主说的应该是因为虚拟机的字符串优化策略有关。由于string是一种不变体,虚拟机会把代码中显式定义的字符串缓存到“字符串池”公用。如有:
    string str1 = "abc";
    string str2 = "def";
    string str3 = "abcdef";那么string对象"abc"、"def"、"abcdef"将存在于“字符串池”中
    现在我在定义:
    str4 = "abcdef"; //这里产生IL: ldstr "abcdef" 虚拟机执行为使用“字符串池”中的对象。
    实际上str4引用str3同一个对象。所以(object)str3 == (object)str4地址相等。但
    str5 = str1 + str2
    (object)str5 != (object)str3,因为str5是经过运算构造出来的新对象。
      

  25.   

    SolidGL(雍软(珠海)研发中心核心成员) 说的很好,支持!!
      

  26.   

    在此感谢雍软珠海研发中心的同行的解释。谢谢:SolidGL(雍软(珠海)研发中心核心成员)
    同样谢谢:hyifeng() ,loulanlouzhu(桃花潭水深千尺,不及阿勇念你情),aspcn(飞刀),SimerJoe(浪月), zhouqi66(部落),c5n() 本着女士优先的CSDN男士风度来说,雍软(珠海)的 SolidGL(雍软(珠海)研发中心核心成员) 更是让偶钦佩之至。所以,致谢的话要说。专家分分之则太少,合之还差不多。不过,妖精,问是你提出来的,虽然 SolidGL(雍软(珠海)研发中心核心成员) 是你的同事,但也请你感谢一下他。这样式,偶给分就给的心安了。555偶要重装上阵,重头再来过了。再次谢谢大家
      

  27.   

    没看那些星星讲什么,只是箱进来和大家讨论讨论,探讨才能进步。using System;
    class Test
    {
       static void Main() {
          string s = "Test";
          string t = string.Copy(s);
          Console.WriteLine(s == t);
          Console.WriteLine((object)s == (object)t);
       }
    }
    produces the outputTrueTrue 
    False
    上面的代码实际相当于下面:string s = "Test";
    string t = string.Copy(s);
    object so =  s;
    object to = t;
    Console.WriteLine(s == t);
    Console.WriteLine(so == to);True 
    FalseTrue// “==”string类(.NET对string类如值类型处理),进行值类型的操作,就像比较int一样比较内存中的“堆栈”,由于两个都是"Test",显然为True
    False //由于(object)s  和(object)t 为两次不同的装箱操作,并且string s 和 string t 在内存“堆”中两个副本的地址不同(但是 string s 和 string t 在“堆栈”中的原始值相同)。对于一般的类如object 类,== 表示比较引用,看是否指向内存(这里指内存中的“堆”,也就是存放副本的地方)中同一个地址。显然为False; ////////////   最最重要的一点是string.Copy()方法!! /////////////////string str1 = "Test";
    string str2 = str; (str1 = "Test"也是一样)
    //上面实际相当于引用,指向str1的内容,内存中只有一个"Test" 
    object s = str1; 
    object t = str2; 
    Console.WriteLine(s == t);结果为:True
    但是下面用了Copy();string str1 = "Test";
    string str2 = string.Copy(str1);//“深层”复制!内存中将有两个"Test"!
    object s = str1; 
    object t = str2; 
    Console.WriteLine(s == t);如 bject o = (object) i;这样的显式执行装箱是毫无必要的
      

  28.   

    To: HNU(為楚有材,於斯為盛!) 
    你的例子写的不错,注释的很好
    真想把这个贴子改成示结的贴子.
    不过,说实话 .Net 的内存管理同想象中的真是不一样.或者说,还不全是同一概念.