【星星三角激辩问题!请进来一起甄别秋毫】C#中的对象(类的实例)和引用变量(引用实例的那个变量)问题讨论

天乐 2009-02-28 10:58:37
首先,对我的描述中的一些关键名词做出限定,以免因词汇含义不一致而导致不必要的误解。

用作限定名词的示例代码:


class A
{
private int _someData;
public int SomeData
{
get{return _someData;}
set{_someData = value;}
}

public void DoNothing()
{;}
}

class B
{
public void DoWork()
{
A a = new A();
A a1 = a;
object b = (object)a; //此处可以采取隐式转换,但为了明确、醒目起见,使用了强制转换
a.DoNothing();
}
}



对象:类的实例,在上例中,即指new运算符执行时在托管堆上创建的A类的一个实例;
引用变量:偶尔也简称为引用,在上例中即指变量a、a1、b;
托管堆:有时简称堆,但与非托管堆是有区别的,当说到非托管堆时,不会简称为堆 //个人习惯
栈:即堆栈,二者含义一致,堆栈一词可以理解为偏义词

-----------------------------------激情的分割线----------------------------------------------------------------

下面讲讲我的观点,抛砖引玉,望大家不吝赐教!

1、过程分析

A a = new A(); //执行时,在托管堆上创建一个A类的实例,在栈上创建一个引用变量a,该引用变量指向(或称引用)上述实例

A a1 = a; //执行时,没有创建新的A类的实例,在栈上创建了新的引用变量a1,a1与a指向同一个实例,但是a1与a本身存储在栈上的不同位置,并非同一个东西

object b = (object)a; //执行时,没有创建新的A类的实例或object实例,在栈上创建了新的引用变量b,b与a也指向同一个实例,至此,a,a1,b指向均同一个实例

2、关于引用变量

1)引用变量指向一个对象(类的实例),但是引用变量本身并非对象本身,不可混淆,二者存储位置不同。对象存储在堆上,而引用变量存储在栈上。

2)引用变量一旦定义,永远只能指向定义时所确定的类型或其子类型。如上示例中的a,被定义为对A类型的引用,则尝试让a指向其他类型(如object)时编译出错。

3)使用某类型的引用变量时,只能访问实例中在该类型层次上所暴露出来的成员(成员包括字段、属性和方法)



先说这么多吧,欢迎大家斧正,感谢大家参与!

...全文
343 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
vwxyzh 2009-03-18
  • 打赏
  • 举报
回复
看一下这篇文章吧
http://services.social.microsoft.com/feeds/FeedItem?feedId=dae624ea-2aba-4282-a4d7-83a3579c9d07&itemId=c7917e6b-3cf2-452a-b40b-c5ca321db3c1&title=References+are+not+addresses&uri=http%3a%2f%2fblogs.msdn.com%2fericlippert%2farchive%2f2009%2f02%2f17%2freferences-are-not-addresses.aspx&k=fypu7w6lbdNI%2bYOUmLupkB7p1eeKu6HGDGm1uvyKL6I%3d
typeof 2009-03-01
  • 打赏
  • 举报
回复
来了。
only_lonely 2009-03-01
  • 打赏
  • 举报
回复
额···诚恳地希望问题能早些解决,小菜我也心安了
空心兜兜 2009-03-01
  • 打赏
  • 举报
回复
我看看就好,插不上话
king19840811 2009-03-01
  • 打赏
  • 举报
回复
up。
天乐 2009-03-01
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 sp1234 的回复:]
呵呵,上面我只是说明原文中我针对楼主的倾向(并没有想到说者无心听着却极端有意),那么我在这里补充一句哪里的说明:.net的设计可以说是“很纯”的,你可以大胆地将引用对象理解为要么是代表一个实际对象要么是null,因为编译器不会允许任何低层次概念的指针运算(实际上.net就是让你忘记恶习),而CLR内部也默认有严格的验证器机制(而不是像某些旧的语言那样默认不检验类型),同时CLR的垃圾收集机制更加帮助使得你彻底忘记…
[/Quote]

核心争辩就在这里,初学者是否需要明确理解引用变量和它所指向(或称引用)的实例对象的区别。

试想,如果不加区分,在初学者眼里,a,a1就会被理解为和它所指向的对象是同一个东西。

那么,在遭遇ref关键字时,这种理解就会带来很大的问题。你将如何为初学者解释使用ref方法时发生的事情呢?


我更加倾向 四角的观点:
引用变量作为参数时传递的是对象的引用,其实它仍然是值传递,只不过这里的值,是对象的引用,即地址,型参中引用变量

我认为仍然从较为底层的观点来分辨,才能把握ref的实质,让初学者也能够清晰理解,不至于在使用中犯错。

盼释疑。
天乐 2009-03-01
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sp1234 的回复:]
另外,原文中楼主的问题是:我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...(省略号是原文作者写的)

你把这里的“类的地址传给了接口”的问题原文掩盖起来,断章取义地从我劝他“不要玩什么“地址”概念,也就不会有此多此一举的困惑”开始抄录,其实是过于故意夸张了我的上下文意思了。
[/Quote]

这里不是故意忽略那个问题,而是本贴就是想集中焦点来探讨对象、引用变量,不想被让大家的注意力被其他问题所吸引,去解释接口、继承、方法等问题。

集中焦点探讨一个问题,是本贴的主旨。
天乐 2009-03-01
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 sp1234 的回复:]

引用变量”并不等于c++的指针,实际上封装为引用变量比简单的指针不知道要复杂几十倍,目的就是避免错误地滥用指针(例如把一个指向ABC类型的对象的指针赋值给指向XYZ类型的对象的指针)。这里,强调的是“并不等于”指针,而如果你硬要理解为我说的是“并不能用指针来举例类比”就太夸张我的意思了。
[/Quote]

我本人也是持与你此段描述相同的观点。

我也从未说过引用变量就是指针,若拿它与指针比较时,我一般会说它近似的可以理解为类型安全的指针。类型安全的保障,即本贴所述:

2)引用变量一旦定义,永远只能指向定义时所确定的类型或其子类型。如上示例中的a,被定义为对A类型的引用,则尝试让a指向其他类型(如object)时编译出错。




JaggerLee 2009-03-01
  • 打赏
  • 举报
回复
四星与四角的观点一个处于CLR上层,一个在CLR下层,一个是OO的逻辑,一个是具体的实现。
其实没什么好争辨的

仅仅是楼主与原帖那位楼主的理解错误加之 四星与四角争辨 这个相当有诱惑的“狗仔队最爱”所导致的而已
Crazy_Xia 2009-03-01
  • 打赏
  • 举报
回复
另外,上面的各位星星众不也是都对底层实现有深入的了解么
在这个基础上再来从更抽象的层次上把握大局不是更能有效分析系统的各个部分么
我觉得对底层实现和从抽象层次上去理解系统都是很重要的
另外我觉得软件工业也是介于科学和工业之间的,既要追求科学的严谨也要符合实际需求
至少我就觉得德国车更值得信赖。。。
Crazy_Xia 2009-03-01
  • 打赏
  • 举报
回复
恩,我承认我是有点专牛角尖
不过我还是认为将声明的引用变量解释为对象本身还是不严谨的,很多情况下会误导人

另外,现在开发项目确实应该从需求、业务实现、人力成本、开发周期上着手,软件工业化肯定是软件行业巨大的进步,这也是java和.net诞生的原因

不过,作为在这个行业中的个体来说,了解更多实现的本质对个人的成长还是很有必要的,了解底层并不一定就要去开发编译器或者去写个操作系统
但是这对开发高质量和高效率的产品还是很有帮助的,至少遇到一个问题时你能根据实际需要做出更适合的选择
yuanmanguo 2009-03-01
  • 打赏
  • 举报
回复
有点深奥,看看
amandag 2009-03-01
  • 打赏
  • 举报
回复
看看
天乐 2009-03-01
  • 打赏
  • 举报
回复
结贴了。
  • 打赏
  • 举报
回复
呵呵,上面我只是说明原文中我针对楼主的倾向(并没有想到说者无心听着却极端有意),那么我在这里补充一句哪里的说明:.net的设计可以说是“很纯”的,你可以大胆地将引用对象理解为要么是代表一个实际对象要么是null,因为编译器不会允许任何低层次概念的指针运算(实际上.net就是让你忘记恶习),而CLR内部也默认有严格的验证器机制(而不是像某些旧的语言那样默认不检验类型),同时CLR的垃圾收集机制更加帮助使得你彻底忘记过时的那些指针编程概念。
  • 打赏
  • 举报
回复
我并不否认你可以从任何一个语法标准的某一个产品的实现的角度来解释运行时机制的可取性。关于不同的产品实现是否可以抽象上升为语法和语用知识,这个没有什么可激辩的。
  • 打赏
  • 举报
回复
另外,原文中楼主的问题是:我的问题是,类的地址传给了接口,这样的隐式转换没问题吗?我只看到过,继承类可以隐式地转换给基类... ...(省略号是原文作者写的)

你把这里的“类的地址传给了接口”的问题原文掩盖起来,断章取义地从我劝他“不要玩什么“地址”概念,也就不会有此多此一举的困惑”开始抄录,其实是过于故意夸张了我的上下文意思了。
  • 打赏
  • 举报
回复
呵呵,这个问题其实进入“灰色地带了”。

仔细看上下文描述,你可以看到为什么要那么说,而不是抠字眼。“引用变量”并不等于c++的指针,实际上封装为引用变量比简单的指针不知道要复杂几十倍,目的就是避免错误地滥用指针(例如把一个指向ABC类型的对象的指针赋值给指向XYZ类型的对象的指针)。这里,强调的是“并不等于”指针,而如果你硬要理解为我说的是“并不能用指针来举例类比”就太夸张我的意思了。

如果我们抠字眼,实际上我们看看csdn,几乎所有关于讲解代码时对“对象”的概念似乎都应该被纠正为“对象的引用”才正确?!再看看我们的生活,如果我说“我要上街去买衣服”你是否要求我必须纠正为“我要上街去买衣服的实例”才算区分了类型和类型实例?实际上我们往往都是基于“对上下文理解”名词概念的,而不是对照着自己手中的一本小词典来理解别人的语言。我们理解所说的是变量的运行时使用概念,并且知道多余的概念是没有附加价值的,就可以了。
cc_net 2009-03-01
  • 打赏
  • 举报
回复
引用对象--》实例对象---》实例类型对象

引用对象在栈上,实例对象在GC堆或大对象堆上,实例类型对象在默认程序域的加载堆上

关于.NET内存结构MSDN上有,大家可以看看

http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true
天乐 2009-03-01
  • 打赏
  • 举报
回复
期待大家最终能有个清晰的版本
加载更多回复(7)
连社恐的鸟鸟,现在都变成话痨了…… (这到底是人性的扭曲,还是道德的沦丧) 最近有一种很新的脱口秀:不花钱、一对一、而且任意话题随便and随时聊。 结果一小时跟鸟鸟聊天下来,发现她话多且密,根本就不会把天聊死。 阿里搞出脱口秀版GPT!与鸟鸟激辩一小时,话痨到停不下来。 (这样的语速和情绪,倒是差点被烦死了。) 原来啊,是一个阿里新版本大模型的技术演示脱口秀版GPT——鸟鸟分鸟,并且已经在天猫精灵上为个人终端行业的客户做了演示,量子位抢先体验了一把。 激辩一小时宛如真人面对面,除了社恐这点人设崩塌以外,其他人设倒是屹立不倒: 文本扛把子、有知识有自己的情绪、还能随时来个段子。尤其是在回答弱智吧问题时,简直被她折服。 这不是脱口秀版GPT,这是科技与狠活呀!哥们! 话不多说,直接上效果。 与弱智吧激辩一小时 鸟鸟分鸟,AKA脱口秀GPT。 作为一名脱口秀演员,鸟鸟最强还是在文本。那就首先来试试强项,结果就是说,任意话题都能展开,甚至还能教你写段子、写作文—— 从开头、场景细节、心思想细化,最后微调润色等步骤逐步教你入手。 毕竟是文本の神,这些当然不在话下。可以看到,不管是在语速、情绪

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧