小弟在论坛上发表了一篇帖子,想寻求正确的答案
 http://topic.csdn.net/u/20090227/15/1b3226fb-b13c-4755-9ce0-ac70a20a0b67.html 
没想到引起了两位大牛看似不同的回答... ...
   
  先交代下前提 
   
     public class MyClass : IMyInterface, IMyInterface2  四星用户的观点是:
       基本上,那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址。 在.net中,对象就是对象,你不要玩什么“地址”概念,也就不会有此多此一举的困惑。对象有HashCode,但是归根结底还是对象的类型转换,而不是什么地址在两个对象之间的赋值。 
            MyClass x = new MyClass(); 
          MyClass y=x; 
          IMyInterface a=(IMInterface)x; 
          IMyInterface2 b=(IMInterface2)x; 
          Object c=x; 这里,x、y、a、b、c,都是同一个对象,而不是什么地址相同的不同对象。调用a定义的某个方法,其实就是调用x所代表的对象的那个方法,也同时就是调用b多代表的那个对象的那个方法。你甚至可以写:             IMyInterface2 d=(IMInterface2)a; 对毫不相干的类型的对象进行强制类型转换。
          如果你打印     x.GetHashCode(); 
    y.GetHashCode(); 
    a.GetHashCode(); 
    b.GetHashCode(); 
    c.GetHashCode(); 
    d.GetHashCode(); 你会发现是完全一样的。有人说,如果类型B继承自A,那么B的实例中就有一个私有对象指向内部的一个A类型的对象,这是错误的结论,则往往给你带到错误的概念上去推理。在多年以前某些c++的书籍作者是这样写的,甚至某些c++实现也真的是那样实现的,但是这是一个对继承的误解。至少在.net中,并不是这样的。 
那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址  -->  那个大牛们是看c++入门书走火入魔了,所以生搬硬套地说.net的对象是地址
----------------------------------------------------------------------------------------------------四角用户的观点是 :
    在这里可以将接口看成是一个纯抽象类,其实实现它的类跟它也是继承关系,它们之间也可以看成是"is a"关系。 
只是接口更强调的是对外部提供了那些操作,继承它的类一定要实现它的方法,所以你知道如果一个类继承了一个接口的话,那么 
这个类一定提供了接口中声明的方法的实现。 你可以将接口看成是提供了一种标准,比如客户提出一个标准,只要我给出满足这个标准的插件,就一定能在客户的程序中正常使用。 
    要了解基本原理就要了解本质,归根结底程序还是对内存块的操作,了解c的对象和指针无疑对.net中的 
对象的理解有很大帮助。   MyClass x = new MyClass(); 
  MyClass y=x; 
  IMyInterface a=(IMInterface)x; 
          IMyInterface2 b=(IMInterface2)x; 
          Object c=x; 这里的x,y,a,b,c其实并不是对象,而是类型分别为MyClass,IMyInterface,Object的引用变量,这些变量的值其实是整型,对应内存中的一个地址,而这个地址就是存储对象的内存块的起始地址。 
而真正的对象是通过new操作符在内存中创建的那段内存中的数据结构。 做个很简单的实验: C# code
using System;public class Program
{
    static void Main()
    {
        A obj1 = new A();
        A obj2 = new A();
        
        obj1.i = 10;    
        Method1(obj1);
        Console.WriteLine(obj1.i.ToString());
        
        obj2.i = 10;
        Method2(ref obj2);
        Console.WriteLine(obj2.i.ToString());
    }
    
    static void Method1(A obj)
    {
        Console.WriteLine((++obj.i).ToString());
    }
    
    static void Method2(ref A obj)
    {
        Console.WriteLine((++obj.i).ToString())    ;
    }
}public class A
{
    public int i;    
}输出:---------------- 
11 
11 
11 
11 
C# code
using System;public class Program
{
    static void Main()
    {
        A obj1 = new A();
        A obj2 = new A();
        
        obj1.i = 10;    
        Method1(obj1);
        Console.WriteLine(obj1.i.ToString());
        
        obj2.i = 10;
        Method2(ref obj2);
        Console.WriteLine(obj2.i.ToString());
    }
    
    static void Method1(A obj)
    {
        obj = new A();
        obj.i = 15;

        Console.WriteLine(obj.i.ToString());
    }
    
    static void Method2(ref A obj)
    {
        obj = new A();
        obj.i = 15;

        Console.WriteLine(obj.i.ToString())    ;
    }
}public class A
{
    public int i;    
}输出: 
15 
10 
15 
15 可以看出,例1中的两个方法都改变了实参,而例2中obj1却没有被改变。为什么 
如果不知道传参的实质的话这里是很难解释的。 引用变量作为参数时传递的是对象的引用,其实它任然是值传递,只不过这里的值,是对象的引用,即地址,型参中引用变量 
obj拷贝了它的实参obj1的值,即obj1指向的对象地址,所以,直接通过型参obj去改变对象的状态也会影响到Main中的obj1, 
此时相当于 
形参-------->堆中的数据结构 <------------实参 
而如果加上ref强制进行引用传递,此时实际上是将值类型A的引用变量的引用传给了形参,此时的形参相当于引用的引用,即指针的指针,所以此时声明一个新对象并将其引用赋给形参会影响到实参,而同样的操作用值传递就不会影响到实参 
此时相当于 
形参------->实参--------->堆中的数据结构 
C#的核心仍然是C++ 
CLR也只不过是运行在宿主进程上的一个软件层罢了,归根结底程序运行的机制是相同的,只不过C#是类型安全的而且不允许 
使用指针罢了,但是通过标记标记unsafe仍然可以使用指针 C++是源头啊,源头啊,源头啊,源头啊(回想1万遍啊1万遍) 
就如同汇编是老祖宗啊老祖宗 
就如同其实都是机器码啊机器码 以上,就是不喜欢看见有人说C++是什么走火入魔阿门

解决方案 »

  1.   

      可怜天下小菜心,100分又出去了,谁叫这是最基础的思想问题,思想不弄错了,以后就麻烦了
      望各位大牛给出中肯的回答
      不要 在C#版答案是A
          换在C++版 答案是B
      

  2.   

      可怜天下小菜心,100分又出去了,谁叫这是最基础的思想问题,思想弄错了,以后就麻烦了
      望各位大牛给出中肯的回答
      不要 在C#版答案是A
          换在C++版 答案是B
      

  3.   

    C#是彻底的面向对象语言,所有的数据,即便是简单的数字类型,都是对象,
    所以我不太赞同四角用户所说的“x,y,a,b,c其实并不是对象”
      

  4.   

    c#与c++某些理论可能不同,在C#中,所有的东西你认为是对象。当你返回某个类的实例时候(如果继承了某个interface),那么看需求而定,如果你只需要使用接口,那么就申明接口对象,具体看情况而定,再说面向接口编程也是不错的。
      

  5.   

    http://industry.ccidnet.com/art/1077/20031009/689837_1.html
    C#中类对象的特征.
      

  6.   

    http://topic.csdn.net/u/20090227/15/1b3226fb-b13c-4755-9ce0-ac70a20a0b67.html
    ==
    已回
      

  7.   

    好像总有人喜欢把C和C#联系起来,如果要有联系,我认为C#和JAVA的联系更大,而不是C
      

  8.   

    那我也插个题外话,不要以为星星有多么的牛叉,其实在csdn混出个星星是很容易的
      

  9.   


    reflect ,
    还不明白

    asm 
    计算机底层没有面向对象
    .net 再先进也脱离不了底层的束缚 ,如何实现面向对象方法,还基本是c++的扩充,不过是vptr vptb
      

  10.   

    没在大学课程里系统学习过C&C++的一定要补一下基本知识了,这是类的基本概念1、SP1234的观点的基本要义没什么偏差,而且比较务实、实用;2、讨论的核心其实是new和=,其实很简单明了:
       new运算大家都清楚,就不说了;   对象实例的=运算:MyClass y=x
       在C++里就是传址引用,也就是说变量名称虽然是不同的物理地址,但都是引用同一个实例的地址;
       在C#里表面上是实现了相同的效果,也就是说C#只是给我们虚拟了“传址引用”的效果
       至于地址是不是一样(我想是不一样的)你不必关心,
       同样道理,C#的指针也是是封装过的(或者说是虚拟的),并不是C++的指针,只不过让你能用罢了,
       所以我会拿C#跟Java相提并论而不是C++。
             由于水平有限,欢迎大家批评指正!
      

  11.   

    2个都有问题,都不在关键点上,关键点是Type的方法表和对象的创建时候的内存分配机制,所以从这个意义上C#和C++的对象管理机制大同小异,所以用c++的观念解释是行的通滴至于4角的解释:正确是正确,不过并不是lz所要问的问题,装箱与拆箱和ref区别 ,这种东西与本例讨论继承与类型转换无直接关系对象分配其他细节我已经在你另一个帖子回了,这里就不做答了
      

  12.   

    还是画图把class C:IA,IB
    {
    }
          --------------传说中的分隔线----------------
          
            --------------------------  --------------
            |   对象c 方法表           |        |
          ----------------------------         |           -----------------
            |   Type IA方法表          |         |                IA的方法表
            |    Method()方法        |       对象C全部方法
            -------------------------        包括 所有IA     -----------------------------
            |  type IB方法表           |         IB的方法
            |    method2()方法         |         |                                  IC的方法表
            ------------------------------------------------------------------------------现在看明白了吗,这个东西
       IA b=new class c();
    就是表明,使用对一个类型为C的对象使用 IA的方法表
      对象b还是对象b,并没有变,只是表明他现在使用的是IA的方法表
      

  13.   

    已开贴讨论争论问题所在,请大家移步继续http://topic.csdn.net/u/20090228/22/2ae369ec-2531-44ad-9c0e-d3b7ed1658d5.html
      

  14.   

    看了一下引发这个事件的帖子
    基本上是楼主在偷换概念四星用户和四角用户,一个说C#的面向对象逻辑概念,一个说实际运行的内存机制没有任何冲突
    他们之间的冲突仅仅在于
    四星用户说的 "基本上,那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址。"仅仅在于这句话,而这句话的根源就是楼主在那个帖子中的帖后PS的所谓 "大牛" 的对于.NET的歪歪理解.
      

  15.   

    我也认为x、y、a、b、c是对象
      

  16.   

    可能我用“走火入魔”这个词是在当时那个帖子的楼主的问题的一种反映而已,我可能当时并没有说明为什么。实际上,.NET的CLR设计在不同的版本中也有着很大变化,不变的是它的比COM时代完善几十倍的语义。CLR的设计初衷本来就是对于COM时代的指针编程的奇技淫巧的终结,它把所有指针概念都封装起来,而且异常复杂地封装起来,而且一步步撇干净非托管程序的影子。在CLR中,编程者眼中只要有类型、属性、方法的签名信息,就可以编程。于是,我们只要做好.NET的应用系统设计者,而不需要自己作为一个CLR设计者,就可以了。学习.Net开发技术,看懂.net framework的源代码就可以了,而不一定需要看懂各个版本以及各个硬件平台下的CLR代码。CLR提交了国际标准,用来从语法和语用的角度使得CLR成为一个全面的各种编程平台都可以交流的底层平台,而不会像COM时代那样各种编程平台实际上根本无法交流。我是从这个角度,在那个帖子中试图说明“只要掌握对象编程的要求就可以了,使用CLR的某个实现版本来的具体属于作为抽象的CLR应用术语是多此一举”。我并不否认可以从某种实现机制来说明程序在某个特定版本系统上运行的底层机制,事实上我在那篇帖子的回复中说过某些c++就是那种方式实现的,只不过说者无心听者有意,把一个版本对语义的特例实现当作永远不变的词典来对照以后的所有实现,没有必要。
      

  17.   

    使用CLR的某个实现版本来的具体属于作为抽象的CLR应用术语是多此一举   -->   使用CLR的某个实现版本来的具体术语取代作为抽象的CLR应用术语是多此一举
      

  18.   

    实际上,我们编写的非托管c#程序,编译为DLL之后,此时并没有汇编进底层概念,如果我们看编译结果它还是面向对象程序概念。只有被JIT运行它们时那些最底层的地址转换等才真正出现。
      

  19.   

    c++与c#很多东西是不好比较的,
    虽然都是面向对象的,但是到底是两个不同的语言。
    个人是这么分析的:
    c++    一代面向对象
    c#     二代面向对象不过个人比较认同C#中一切对象化的理论。