我试图验证我对C#/。NET/CLR如何处理值类型和引用类型的理解。我读了很多矛盾的解释

这就是我今天所了解的,如果我的假设是错误的,请纠正我。

诸如int等值类型存在于堆栈中,引用类型存在于托管堆中但是如果引用类型具有例如double类型的实例变量,它将与对象一起存在于堆中

第二部分是我最困惑的地方。

让我们考虑一个称为Person的简单类。

Person具有一个名为Name的属性。

假设我在另一个类中创建Person的实例,我们将其称为UselessUtilityClass。

考虑以下代码:

class UselessUtilityClass
{
   void AppendWithUnderScore(Person p)
   {
     p.Name = p.Name + "_";
   }
}

然后在某个地方做:
Person p = new Person();
p.Name = "Priest";
UselessUtilityClass u = new UselessUtilityClass();
u.AppendWithUnderScore(p);

Person是引用类型,当传递给UselessUtilityClass时-这是我要去的地方-坚果...作为Person引用实例的 VARIABLE p由 VALUE 传递,这意味着我编写p.Name时我会看到“Priest_”

然后如果我写
Person p2 = p;

而我

p2.Name =“不是牧师”;

并按如下所示输入p的名称,我会得到“不是牧师”
Console.WriteLine(p.Name) // will print "Not a Priest"

这是因为它们是引用类型,并且指向内存中的相同地址。

我的理解正确吗?

我认为人们说时会发生一些误解,.NET中的所有对象都是通过引用传递的,这并不是基于我的想法。我可能是错的,这就是为什么我来到堆高机。

最佳答案



不,这是不正确的。正确的说法是“既不在迭代器块中也不是lambda或匿名方法的封闭外部变量的局部变量和值类型的形式参数在CLI的Microsoft实现中分配在执行线程的系统堆栈上以及Microsoft的C#实现。”

不需要任何C#版本或CLI版本都可将系统堆栈用于任何用途。当然,我们这样做是因为它对于不直接位于迭代器块或lambda或匿名方法的封闭外部变量中的局部变量和值类型的形式参数是一种方便的数据结构。

请参阅我在该主题上的文章,以讨论以下内容:(1)为什么这是实现细节,(2)我们从这种实现选择中获得了什么好处,以及(3)做出此实现选择的愿望受到哪些限制?语言设计。

http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx



深吸一口气。

变量是存储位置。每个存储位置都有一个关联的类型。

其关联类型是引用类型的存储位置可能包含对该类型对象的引用,也可能包含空引用。

其关联类型是值类型的存储位置始终包含该类型的对象。

变量的值是存储位置的内容。



变量p是一个存储位置。它包含对Person实例的引用。因此,变量的值是对Person的引用。该值(对实例的引用)将传递给被调用方。现在另一个令人困惑的变量也称为“p”,它包含相同的值-该值是对特定对象的引用。

现在,还可以将引用传递给变量,这使很多人感到困惑。一种更好的思考方式是当您说

void Foo(ref int x) { x = 10; }
...
int p = 3456;
Foo(ref p);

这意味着“x是变量p的别名”。也就是说,x和p是同一变量的两个名称。因此,无论p的值是多少,x的值也一样,因为它们是同一存储位置的两个名称。

现在有意义吗?

关于c# - .NET参数传递-按值传递引用值v/s,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2125591/

10-17 01:58