Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么样的内存语义控制c#中的数组分配?_C#_.net - Fatal编程技术网

什么样的内存语义控制c#中的数组分配?

什么样的内存语义控制c#中的数组分配?,c#,.net,C#,.net,给定以下内容:字节[]sData和声明为专用字节[]的函数构造\u命令() 如果我随后将construct_command()的结果分配给sData sData是否只指向从函数返回的内容,或者是否会在内存中为sData分配一些空间,并将函数结果的内容复制到其中?sData将指向从函数返回的内容。C#中的数组是引用类型,这意味着从另一个数组分配一个数组只是复制引用,而不是分配新数据。假设sData是一个局部变量,它将存在于堆栈中,并将引用该方法返回的数组。该方法不返回数组本身的内容,而是返回对数组

给定以下内容:字节[]sData和声明为专用字节[]的函数构造\u命令()

如果我随后将construct_command()的结果分配给sData
sData是否只指向从函数返回的内容,或者是否会在内存中为sData分配一些空间,并将函数结果的内容复制到其中?

sData将指向从函数返回的内容。C#中的数组是引用类型,这意味着从另一个数组分配一个数组只是复制引用,而不是分配新数据。

假设sData是一个局部变量,它将存在于堆栈中,并将引用该方法返回的数组。该方法不返回数组本身的内容,而是返回对数组的引用


在.net中,数组是第一类对象,所有数组类型变量实际上都是引用。

赋值将简单地分配sData以引用construct_命令返回的实例。不会复制数据

一般来说,CLR将世界分为两种类型

  • 值类型:这是从System.ValueType派生的任何内容。这些类型的值之间的赋值是按值进行的,基本上会导致位置之间的值的副本
  • 引用类型:任何其他类型。这些类型的值之间的赋值只会导致位置引用内存中的不同对象。不会复制值

数组是CLR中的引用类型,因此不会导致基础值的复制

sData
将指向
construct\u命令返回的数组
数组是引用类型,因此只复制引用。没有内容操作。

数组是引用类型,这意味着实际数组在堆上实例化(可能是通过construct_command()),函数返回对数组的引用,并存储在(局部变量)sData中

因此,这实际上不是关于内存语义(返回值可以为null),而是关于引用类型的复制语义。情况完全相同,例如:

StreamReader reader = System.IO.File.OpenText(filename);

更直截了当地说:你根本无法在.Net中传递数组,你只能传递、复制和分配对数组的引用。

虽然Rui的答案总体上是正确的,但我确实认为其中一部分是错误的。从堆栈内存中分配一个数组,然后通过引用访问它是没有意义的(非常不一致)。如果这是真的,那么底层内存可以从传递引用的任何方法下面释放出来

我相信亨克·霍尔特曼(Henk Holterman)的描述是正确的,他非常直接、毫不含糊地说:


数组是引用类型,这意味着实际数组是 在堆上实例化

感谢亨克的评论;我认为这是一个关键的部分,否则就会被公认的答案遗漏(并与之相矛盾)


(我本来会回复一条评论,但我没有足够的分数来回复,我认为重要的是要指出接受的答案有这个问题,我需要在这里添加一条新评论。)也许管理员可以删除对“局部变量,它将存在于堆栈中”的引用从答案来看。

这是否意味着在包含局部变量(sData)的方法返回之前存在内容被破坏的危险?否,因为垃圾收集器将知道数组仍然被引用。