【问题标题】:Reference type v. Value type引用类型 v. 值类型
【发布时间】:2014-09-21 08:23:22
【问题描述】:

我有一个问题。当我做一个

 Int32 ii = new Int32();

我是否正在创建具有标识符“ii”的引用类型的值类型?如果我正在创建一个引用类型,那么当我将该引用的副本传递给一个更改其值的方法时,当方法返回时我看不到更改是怎么回事?当我运行下面的代码时,我得到“0”。

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {


            Int32 ii = new Int32();

            changeit(ii);
            Console.WriteLine(ii.ToString());
            Console.ReadLine();


        }

        static void changeit (Int32 i) 
        {
            i = 2;
        }

        static void changeit(ref int i)
        {
            i = 2;
        }
    }
}

【问题讨论】:

  • new 不会将值类型更改为引用类型。
  • 因为你调用了错误的函数。只需执行changeit(ref li),您就会看到值的变化。
  • @tnw 这是按引用传递值类型,而不是按值传递引用类型,正如他所期望的那样。它通过意想不到的方式创造了预期的结果,阻碍了对相关概念的理解。
  • 谢谢大家。每次我认为我理解并离开时,它总是把我拉回来。

标签: c# pass-by-reference


【解决方案1】:

new 运算符对于值和引用类型有不同的含义。对于引用类型,就是在堆上分配初始化类型;对于值类型,这意味着仅初始化。所以

int i=new int();

一样
int i=0;

首先请参阅C# reference

【讨论】:

    【解决方案2】:

    如果我正在创建引用类型

    您没有创建引用类型。使用new 不会将值类型更改为引用类型。

        static void Main(string[] args)
        {
    
    
            Int32 ii = new Int32();
    
            changeit1(ii);
            Console.WriteLine(ii.ToString());
            changeit2(ref ii);
            Console.WriteLine(ii.ToString());
            Console.ReadLine();
    
    
        }
    
        static void changeit1(Int32 i) 
        {
            i = 2;
        }
    
        static void changeit2(ref int i)
        {
            i = 2;
        }
    

    结果:

    0

    2

    【讨论】:

      【解决方案3】:

      Int32 根据定义是一种值类型。根据定义,类型可以是值类型或引用类型,您无法更改。

      如果你希望你的 Int32 被修改,你应该使用 "ref" 关键字来传递它:

      static void changeit(ref int i)
          {
              i = 2;
          }
      

      完成类似事情的唯一方法是将 Int32 封装在一个类中,例如:

      public class DumbClass{
        public int YourInt {get; set;}
      }
      

      当您将整数作为属性时,您可以更改它,发送您的 DumbClass 参考:

      static void changeit(DumbClass c)
          {
              c.YourInt = 2;
          }
      

      这是因为类是引用类型(根据定义)。

      在引擎盖内部,会发生很多事情。框架可能会决定在堆栈或堆中分配变量,具体取决于操作系统的心情(因为有时会发生优化)。

      通常当你在方法中声明一个 int 时,它是在堆栈上分配的,因为当方法完成它的执行时它会被释放,如果它是一个引用类型会很奇怪。

      这就是框架内部存在“装箱”和“拆箱”的原因。有时值类型是“装箱的”,因此您可以将其用作引用类型(并在托管堆上分配)。就个人而言,我不知道是否有办法在 C# 中明确地做到这一点,以及是否有意义。

      【讨论】:

      • 谢谢埃里克。这是一个很棒的解释。
      猜你喜欢
      • 2012-07-20
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 2010-12-04
      • 2012-03-09
      相关资源
      最近更新 更多