小弟在论坛上发表了一篇帖子,想寻求正确的答案
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++是什么走火入魔阿门
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++是什么走火入魔阿门
解决方案 »
- C#中正则表达式如何去使用?
- C# datagridview 更新
- 求教各位,这样要这么判断!!!
- Radio在WinForm分组的问题
- serialport配合timer控件发送数据的问题
- C#怎样写一个登陆的程序
- 有没有办法能知道DataTable里的字段属于数据库中的什么数据类型? 就是找出是SqlDbType的值.
- 请那有省份,城市邮编的数据库,麻烦给我发一份。
- 从串口读取数据,把需要的数据存入数据库出错
- 在crystal report中我绑定两个表到DATASET中,table[1]空时table[0]的数据也没有显示,为什么?
- dataReader连接数据库若该字段为空则错误,大侠指点下
- .net怎么可以控制一个控件的事件无效?
望各位大牛给出中肯的回答
不要 在C#版答案是A
换在C++版 答案是B
望各位大牛给出中肯的回答
不要 在C#版答案是A
换在C++版 答案是B
所以我不太赞同四角用户所说的“x,y,a,b,c其实并不是对象”
C#中类对象的特征.
==
已回
reflect ,
还不明白
再
asm
计算机底层没有面向对象
.net 再先进也脱离不了底层的束缚 ,如何实现面向对象方法,还基本是c++的扩充,不过是vptr vptb
new运算大家都清楚,就不说了; 对象实例的=运算:MyClass y=x
在C++里就是传址引用,也就是说变量名称虽然是不同的物理地址,但都是引用同一个实例的地址;
在C#里表面上是实现了相同的效果,也就是说C#只是给我们虚拟了“传址引用”的效果,
至于地址是不是一样(我想是不一样的)你不必关心,
同样道理,C#的指针也是是封装过的(或者说是虚拟的),并不是C++的指针,只不过让你能用罢了,
所以我会拿C#跟Java相提并论而不是C++。
由于水平有限,欢迎大家批评指正!
{
}
--------------传说中的分隔线----------------
-------------------------- --------------
| 对象c 方法表 | |
---------------------------- | -----------------
| Type IA方法表 | | IA的方法表
| Method()方法 | 对象C全部方法
------------------------- 包括 所有IA -----------------------------
| type IB方法表 | IB的方法
| method2()方法 | | IC的方法表
------------------------------------------------------------------------------现在看明白了吗,这个东西
IA b=new class c();
就是表明,使用对一个类型为C的对象使用 IA的方法表
对象b还是对象b,并没有变,只是表明他现在使用的是IA的方法表
基本上是楼主在偷换概念四星用户和四角用户,一个说C#的面向对象逻辑概念,一个说实际运行的内存机制没有任何冲突
他们之间的冲突仅仅在于
四星用户说的 "基本上,那个大牛们是看c入门书走火入门了,所以生搬硬套地说.net的对象是地址。"仅仅在于这句话,而这句话的根源就是楼主在那个帖子中的帖后PS的所谓 "大牛" 的对于.NET的歪歪理解.
虽然都是面向对象的,但是到底是两个不同的语言。
个人是这么分析的:
c++ 一代面向对象
c# 二代面向对象不过个人比较认同C#中一切对象化的理论。