c# - 装箱值类型以将其发送到方法并获取结果

标签 c# pass-by-reference value-type boxing reference-type

我很好奇 C# 在将值/引用类型传递给方法时的行为方式。我想将一个装箱值类型传递给方法“AddThree”。这个想法是在调用函数 (Main) 中获取在“AddThree”中执行的操作的结果。

static void Main(string[] args)
{
    int age = 3;
    object myBox = age;
    AddThree(myBox);
    // here myBox = 3 but I was expecting to be  = 6
}

private static void AddThree(object age2)
{
    age2 = (int)age2 + 3;
}

我已经用像 string 这样的纯引用类型试过了,我得到了相同的结果。如果我在一个类中“包装”我的 int 并在此示例中使用“包装”类,它会按预期工作,即,我得到 myBox = 6。如果我修改“AddThree”方法签名通过 ref 传递参数,这也返回 6。但是,我不想修改签名或创建包装类,我只想装箱值。

最佳答案

I don't want to modify the signature or create a wrapper class, I want to just box the value.

那就麻烦了。你的方法传递一个装箱的 int,然后将它拆箱并将 3 添加到本地 age2,这会导致另一个装箱操作,然后丢弃该值。事实上,您正在将 age2 分配给堆上的两个不同对象,它们不指向同一个对象。 如果不修改方法签名,这是不可能的。

如果您查看为 AddThree 生成的 IL,您会清楚地看到:

AddThree:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  unbox.any   System.Int32 // unbox age2
IL_0007:  ldc.i4.3    // load 3
IL_0008:  add         // add the two together
IL_0009:  box         System.Int32 // box the result
IL_000E:  starg.s     00 
IL_0010:  ret    

您取消装箱该值,添加 3,然后再次装箱该值,但您永远不会返回它。

为了进一步形象化这种情况,尝试从方法中返回新装箱的值(只是为了测试),并使用 object.ReferenceEquals 比较它们:

static void Main(string[] args)
{
    int age = 3;
    object myBox = age;
    var otherBox = AddThree(myBox);
    Console.WriteLine(object.ReferenceEquals(otherBox, myBox)); // False
}

private static object AddThree(object age2)
{
    age2 = (int)age2 + 3;
    return age2;
}

关于c# - 装箱值类型以将其发送到方法并获取结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33844438/

相关文章:

c# - 如何确定非空对象是否为可空结构?

c# - Java 枚举与 C# 枚举 - 缺少的功能

c# - ef core - 如何将类映射的多个变体映射到同一个表

c++ - 插入二叉搜索树时出现段错误

c# - 可与 switch() 一起使用的自定义结构/类型

c# - 值类型如何/为什么可能从引用类型派生?

c# 7.0 : switch on System. 类型

c# - 如何使用 MultiSelection ="true"让默认值出现在 MudBlazor MudSelect 中?

C 介绍 - 如何在函数中通过引用传递参数?

java - Java 是 "pass-by-reference"还是 "pass-by-value"?