Dan*_*n P 15 .net c# memory specifications
主要问题是允许在有用性和内存方面修改this关键字的含义是什么; 为什么在C#语言规范中允许这样做?
如果选择这样做,可以回答其他问题/子部分.我认为对它们的回答有助于澄清主要问题的答案.
我试着回答你在C#或.NET中看到的最奇怪的角落是什么?
public struct Teaser
{
public void Foo()
{
this = new Teaser();
}
}
Run Code Online (Sandbox Code Playgroud)
我一直试图解决为什么C#语言规范甚至会允许这样做. 第1部分.有什么可以证明这是可以修改的吗?这一切都有用吗?
该答案的评论之一是
从CLR到C#:他们之所以这样做是因为你可以在另一个构造函数中调用struct的无参数构造函数.如果您只想初始化结构的一个值并希望其他值为零/ null(默认),则可以编写公共Foo(int bar){this = new Foo(); specialVar = bar;}.这样效率不高且不合理(specialVar分配了两次),但仅限于FYI.(这就是书中给出的理由,我不知道为什么我们不应该只做公共Foo(int bar):this())
子部分2. 我不确定我是否遵循这个推理.有人可以澄清他的意思吗?也许是一个如何使用它的具体例子?
编辑(忽略堆栈或堆主要点是关于内存释放或垃圾收集.而不是int []你可以用262144 public int字段替换它)同样从我的理解结构是在堆栈上创建而不是堆栈这个结构有一个1 Mb字节数组字段初始化
public int[] Mb = new int[262144];
Run Code Online (Sandbox Code Playgroud)
子部分3.当调用Foo时,它是否会从堆栈中删除?对我来说,似乎因为结构永远不会超出范围,所以它不会从堆栈中删除.今晚没有时间来创建一个测试用例,但也许明天我会为此做一个.
在下面的代码中
Teaser t1 = new Teaser();
Teaser tPlaceHolder = t1;
t1.Foo();
Run Code Online (Sandbox Code Playgroud)
第4部分.t1和tPlaceHolder是否占用相同或不同的地址空间?
很抱歉提出一个3岁的帖子,但这个确实让我头疼.
我是关于stackoverflow的第一个问题,所以如果我对这个问题有问题,请发表评论,我会编辑.
2天之后,即使我已经选择了一名获胜者,我也会在这个问题上投入50分,因为我认为答案需要合理的工作来解释问题.
首先,我认为你应该首先检查一下你是否提出了正确的问题.或许我们应该问,"为什么C#不容许分配this的结构?"
this在引用类型中分配关键字具有潜在的危险性:您正在覆盖对正在运行的方法的对象的引用; 你甚至可以在初始化该引用的构造函数中这样做.尚不清楚应该是什么行为.为了避免弄清楚,因为它通常不是很有用,所以spec(或编译器)不允许这样做.
this但是,为值类型中的关键字分配是明确定义的.值类型的赋值是复制操作.每个字段的值以递归方式从赋值的右侧到左侧复制.这对结构来说是一个非常安全的操作,即使在构造函数中也是如此,因为结构的原始副本仍然存在,您只是在更改其数据.它完全等同于手动设置结构中的每个字段.为什么规范或编译器禁止定义明确且安全的操作?
顺便说一下,这回答了你的一个子问题.值类型分配是深层复制操作,而不是引用副本.鉴于此代码:
Teaser t1 = new Teaser();
Teaser tPlaceHolder = t1;
t1.Foo();
Run Code Online (Sandbox Code Playgroud)
您已分配了两个Teaser结构副本,并将第一个字段的值复制到第二个字段中.这是值类型的本质:两个具有相同字段的类型是相同的,就像两个int包含10个变量的变量一样,无论它们在"内存中"的哪个位置.
此外,这很重要且值得重复:仔细考虑"堆栈"与"堆"的内容.值类型始终在堆上结束,具体取决于它们的使用环境.没有关闭或以其他方式从其范围中提升的短期(本地范围)结构很可能被分配到堆栈中.但这是一个不重要的实施细节,你既不应该关心也不应该依赖.关键是它们是值类型,并且表现如此.
至于this真正有用的分配方式:不是很好.已经提到了具体的用例.您可以使用它来大多初始化具有默认值的结构,但指定一个小数字.由于您需要在构造函数返回之前设置所有字段,因此可以节省大量冗余代码:
public struct Foo
{
// Fields etc here.
public Foo(int a)
{
this = new Foo();
this.a = a;
}
}
Run Code Online (Sandbox Code Playgroud)
它还可用于执行快速交换操作:
public void SwapValues(MyStruct other)
{
var temp = other;
other = this;
this = temp;
}
Run Code Online (Sandbox Code Playgroud)
除此之外,它只是语言的一个有趣的副作用以及结构和值类型的实现方式,您很可能永远不需要知道.
| 归档时间: |
|
| 查看次数: |
4035 次 |
| 最近记录: |