一切都在bbs因SilenceHeard的一个问题而起。。。
SilenceHeard:
需要引用一个bool值,却找不到方法。求助
int i = 5;
object o = i;
引用的目的是通过o来修改 i 的值
boxing只能负责类型转换。
int i = 5;
object o = i;
对o进行修改以后, i的值还是5。这不是我想要的
方法调用的确可以, 但是我的情况类似于:
private bool a = false;
private bool b = false;
private bool c = false;
...................
private bool i ;
if()
i = ref a;
else if()
i = ref b;
else
i = ref c;
i = true;
不希望再通过函数调用来完成。 很头疼
jewelry:
我不能说解决这个问题,我只是来说说我的理解:)
下面这段汇编作的事情很简单,就是下面的c#代码的编译结果
############# CODE ###############
static void Main(string[] args)
{
bool input1 = true;
bool input2 = true;
changeValueByRef(ref input1);
Console.WriteLine("1. Input is: {0}",input1);
changeValueByPassin(input1);
Console.WriteLine("2. Input is: {0}",input1);
changeValueByPassin(input2);
Console.WriteLine("3. Input is: {0}",input2);
Console.Read();
}
static void changeValueByRef(ref bool b)
{
b ^= true;
}
static void changeValueByPassin(bool b)
{
b ^= true;
}
########## IL ASM ###############
private static void Main(string[] args);
.maxstack 2
.locals (bool V_0, bool V_1)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldc.i4.1
L_0003: stloc.1
L_0004: ldloca.s V_0
L_0006: call Class1.changeValueByRef
L_000b: ldstr "1. Input is: {0}"
L_0010: ldloc.0
L_0011: box bool
L_0016: call Console.WriteLine
L_001b: ldloc.0
L_001c: call Class1.changeValueByPassin
L_0021: ldstr "2. Input is: {0}"
L_0026: ldloc.0
L_0027: box bool
L_002c: call Console.WriteLine
L_0031: ldloc.1
L_0032: call Class1.changeValueByPassin
L_0037: ldstr "3. Input is: {0}"
L_003c: ldloc.1
L_003d: box bool
L_0042: call Console.WriteLine
L_0047: call Console.Read
L_004c: pop
L_004d: ret
注意,里面如果是ref的方式调用,
L_0004: ldloca.s V_0
L_0006: call Class1.changeValueByRef
如果是pass by value,
L_001b: ldloc.0
L_001c: call Class1.changeValueByPassin
or
L_0031: ldloc.1
L_0032: call Class1.changeValueByPassin
这里的ldloc.0和ldloc.1是本地变量,
这说明,两者的压栈方式不同,所以导致了调用方式不同,
那么,具体使用栈里面的东西的函数是什么样的呢?
耐心的看下去,
$$$$$$$$$$$$$$$$ PASS IN $$$$$$$$$$$$$$$$
private static void changeValueByPassin(bool b);
.maxstack 2
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: xor
L_0003: starg.s b
L_0005: ret
$$$$$$$$$$$$$$$$$ BY REF $$$$$$$$$$$$$$
private static void changeValueByRef(ref bool b);
.maxstack 3
L_0000: ldarg.0
L_0001: dup
L_0002: ldind.i1
L_0003: ldc.i4.1
L_0004: xor
L_0005: stind.i1
L_0006: ret
两者最大的不同就是,后者使用ldind.i1来获取可以进行操作计算的值
并且,还把这个值保存了回去:stind.i1, 当然,需要这么做必须dup一下
传入的参数--那个可爱的引用地址,
获取数据的方式一个是直接使用栈顶数值作计算,一个是使用载入内存所指向
的数值并计算,两者自然不同:)
这么废话,不知道大家看懂没有,我只是初步的解释一下,
抛砖引玉:)

