对于.NET类型的一个小问题

runerback 2016-12-07 10:25:56
被人说是什么丢人现眼啥的,很不痛快。自己提一个“高端”问题却使用了“一个基础问题”这样的标题,咋不用“小白求助”呢?
吐槽完了。
先说A a = new B()吧
namespace AanewB
{
public class A
{
public int a = 1;
}
}

namespace AanewB
{
public class B : A
{
public int b = 2;
}
}

namespace AanewB
{
public class C
{
public C()
{
A a = new B();
int i = a.a;
}
}
}

class C的Release版本的IL代码:
.class public auto ansi beforefieldinit AanewB.C
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2070
// Code size 20 (0x14)
.maxstack 1
.locals init (
[0] class AanewB.A a
)

IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: newobj instance void AanewB.B::.ctor()
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: ldfld int32 AanewB.A::a
IL_0012: pop
IL_0013: ret
} // end of method C::.ctor

} // end of class AanewB.C

根据IL_000d那行内容,变量a的类型就是A,去读取变量a的a字段的时候读的是类型A里的a字段太绕口了

然后再说CollectionBase那个 (IList)this 大坑

我猜不截图会让人觉得我在瞎掰


选中这个了,右边只有这个属性的相关代码


这里直接返回 this 了啊

接下来就是我的问题,关于类型转换的,越想越觉得想不通
就拿上面的AB来说,如果把C的构造函数改成这样
public C()
{
B b = new B();
A a = b; //or (A)b
a.a = 0;
}

IL
	.method public hidebysig specialname rtspecialname 
instance void .ctor () cil managed
{
// Method begins at RVA 0x2070
// Code size 22 (0x16)
.maxstack 2
.locals init (
[0] class AanewB.B b,
[1] class AanewB.A a
)

IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: newobj instance void AanewB.B::.ctor()
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: ldc.i4.0
IL_0010: stfld int32 AanewB.A::a
IL_0015: ret
} // end of method C::.ctor

然后从IL_000b到IL_000e那几句,A和B里的a“都被”改成了0,再结合原贴里的思路,很容易让人觉得B里面还有一个A,就像B里有个对A的引用,导致修改了A里的a后,B里的A的a也就变了,对于整个问题,正确的思路是怎么样的?
...全文
178 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wanghui0380 2016-12-07
  • 打赏
  • 举报
回复
问题不高端,原帖上已经说了“名实之辩”,类型其实是名,实例是实。 对实例的修改,当然就是对本体的修改。 你的例子一样,A a=new B() 实际的含义是“把A的名盖到 B名下某个实例头上” 如果你无法理解“名实之辩”,我只能给个不恰当的例子, 把你收手上的房子转到你老婆名下,房子还是房子,房子始终就一个,不是因为你转了一下,这房子就变成2个了
正怒月神 2016-12-07
  • 打赏
  • 举报
回复
然后从IL_000b到IL_000e那几句,A和B里的a“都被”改成了0 小伙子,class是引用类型。当然一起变啊。。。。
  • 打赏
  • 举报
回复
引用 楼主 shaoerbao 的回复:
然后从IL_000b到IL_000e那几句,A和B里的a“都被”改成了0,再结合原贴里的思路,很容易让人觉得B里面还有一个A
你既然贴了代码,然后为什么又改为乱猜的方式? 你贴了代码,却说不出4行代码的每行代码的功能,让人怀疑你有什么必要贴 MSIL 代码。
D56233577 2016-12-07
  • 打赏
  • 举报
回复
常识都没搞清还去猜IL
runerback 2016-12-07
  • 打赏
  • 举报
回复
引用 4 楼 wanghui0380 的回复:
问题不高端,原帖上已经说了“名实之辩”,类型其实是名,实例是实。 对实例的修改,当然就是对本体的修改。 你的例子一样,A a=new B() 实际的含义是“把A的名盖到 B名下某个实例头上” 如果你无法理解“名实之辩”,我只能给个不恰当的例子, 把你收手上的房子转到你老婆名下,房子还是房子,房子始终就一个,不是因为你转了一下,这房子就变成2个了
这么说就清楚了,类型只是用来描述实例的,之前总是盯着类型去看了。
runerback 2016-12-07
  • 打赏
  • 举报
回复
唉真是的。 别人说我是sb,我不承认,又来证明了一次自己确实sb
runerback 2016-12-07
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
[quote=引用 楼主 shaoerbao 的回复:] 然后从IL_000b到IL_000e那几句,A和B里的a“都被”改成了0,再结合原贴里的思路,很容易让人觉得B里面还有一个A
然后为什么又改为乱猜的方式?[/quote] IL_000b: stloc.0 //把b移到调用堆栈的V0 IL_000c: ldloc.0 //把b从V0移到计算堆栈 IL_000d: stloc.1 //把a移到调用堆栈的V1 IL_000e: ldloc.1 //把a从V1移到计算堆栈 IL_000f: ldc.i4.0 //把Int32 0移到计算堆栈 IL_0010: stfld int32 AanewB.A::a //给a和b里的a赋值0 不是这样的吗?

17,740

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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