C#中结构变量的存储方式
How struct variables are stored in C#
我阅读了这个 Whosebug Question
我读了这个博客 here
完全看不懂。
这是我的疑惑。
struct S
{
private int x;
private int y;
public int X { get { return x; } }
public int Y { get { return y; } }
public S(int x, int y, bool panic)
{
this.x = x;
this.y = y;
if (panic)
throw new Exception();
}
}
static class P
{
static void Main()
{
S s = default(S);
try
{
s = new S(1, 2, false);
Console.WriteLine("{0}, {1}", s.X, s.Y);
s = new S(3, 4, true);
}
catch
{
Console.WriteLine("{0}, {1}", s.X, s.Y);
}
Console.ReadLine();
}
}
在抛出异常之前,我在这里分配了值。但为什么它不分配给对象 s 我的意思是在我在 catch 块中编写的控制台中,
说 (1,2)。
因为在第二行又被初始化了,并且用(3,4)调用了构造函数。那么它是如何 (1,2).
我怎么看不懂。
还有,
Therefore, using the new operator on a value type allocates no additional memory. Rather, the memory already allocated for the value is used.
在那篇博客中,答案是否定的
如果是这样,是否正在使用新内存进行初始化。如果是这样, (1,2) 怎么会出现在 catch 块中。
由于我是 C# 的新手,所以我无法理解这一点。
我知道这是愚蠢的疑问,但请有人帮助我理解这个概念。
Because it is initialized again in the second line , and called the constructor with (3,4).
您调用了构造函数,但构造函数本身尚未完成 - 因此对 s
的赋值永远不会发生。
这个:
s = new S(3, 4, true);
相当于:
// Create the new value
S tmp = new S(3, 4, true);
// Copy it into the s variable
s = tmp;
第一个语句永远不会完成,因此不会发生赋值...因此您仍然会在 catch
块中看到 s
的第一个值。
转自博客Debunking another myth about value types:
The C# specification is clear on this point:
"If T is a struct type, an instance of T is created by allocating a temporary local variable"
That is, the statement
s = new S(123, 456);
actually means:
- Determine the location referred to by s.
- Allocate a temporary variable t of type S, initialized to its default value.
- Run the constructor, passing a reference to t for "this".
- Make a by-value copy of t to s.
您在第三阶段抛出异常:
- Run the constructor, passing a reference to t for "this"
意思是最后一个阶段,复制到 s
永远不会发生,因此你看到 s
的当前值,在你的情况下是 1, 2
.
在控制台中打印 s.X 和 s.Y。这是
的第一篇
s = new S(1, 2, false);
第二个赋值永远不会执行,因为抛出了异常。
在等号左侧的 S 赋值之前发生异常。
所以你的 catch 块写出了之前赋值的原始值。
大写S变量是Type,小s是实例。
结构构造函数作为方法实现,这些方法将正在构造的结构作为隐含的 ref
参数。在许多情况下,编译器会执行如下语句:
s = new StructType(4);
相当于
var temp = default(StructType);
StructType..ctor(out temp, 4); // Not possible with C# syntax
s = temp;
然而,在某些情况下它不会这样做,而是简单地这样做:
StructType..ctor(out s, 4);
这可能是可以观察到的,尤其是在与其他语言编写的代码交互时,这些代码不支持 C# 用于标记 out
参数的属性。
例如,虽然不可能在 C# 中编写 IDictionary.TryGetValue
的实现,它不会将 default(TValue)
存储到其 out
参数,但该参数将被看到由其他语言作为 ref
参数;因此,用另一种语言编写的实现可能 return 而无需向其写入任何内容。如果结构构造函数将 this
传递给传入 IDictionary
的 TryGetValue
方法但不执行任何其他操作,则可以观察到结构构造的实际行为。
我阅读了这个 Whosebug Question 我读了这个博客 here
完全看不懂。 这是我的疑惑。
struct S
{
private int x;
private int y;
public int X { get { return x; } }
public int Y { get { return y; } }
public S(int x, int y, bool panic)
{
this.x = x;
this.y = y;
if (panic)
throw new Exception();
}
}
static class P
{
static void Main()
{
S s = default(S);
try
{
s = new S(1, 2, false);
Console.WriteLine("{0}, {1}", s.X, s.Y);
s = new S(3, 4, true);
}
catch
{
Console.WriteLine("{0}, {1}", s.X, s.Y);
}
Console.ReadLine();
}
}
在抛出异常之前,我在这里分配了值。但为什么它不分配给对象 s 我的意思是在我在 catch 块中编写的控制台中, 说 (1,2)。
因为在第二行又被初始化了,并且用(3,4)调用了构造函数。那么它是如何 (1,2).
我怎么看不懂。
还有,
Therefore, using the new operator on a value type allocates no additional memory. Rather, the memory already allocated for the value is used.
在那篇博客中,答案是否定的
如果是这样,是否正在使用新内存进行初始化。如果是这样, (1,2) 怎么会出现在 catch 块中。
由于我是 C# 的新手,所以我无法理解这一点。
我知道这是愚蠢的疑问,但请有人帮助我理解这个概念。
Because it is initialized again in the second line , and called the constructor with (3,4).
您调用了构造函数,但构造函数本身尚未完成 - 因此对 s
的赋值永远不会发生。
这个:
s = new S(3, 4, true);
相当于:
// Create the new value
S tmp = new S(3, 4, true);
// Copy it into the s variable
s = tmp;
第一个语句永远不会完成,因此不会发生赋值...因此您仍然会在 catch
块中看到 s
的第一个值。
转自博客Debunking another myth about value types:
The C# specification is clear on this point:
"If T is a struct type, an instance of T is created by allocating a temporary local variable"
That is, the statement
s = new S(123, 456);
actually means:
- Determine the location referred to by s.
- Allocate a temporary variable t of type S, initialized to its default value.
- Run the constructor, passing a reference to t for "this".
- Make a by-value copy of t to s.
您在第三阶段抛出异常:
- Run the constructor, passing a reference to t for "this"
意思是最后一个阶段,复制到 s
永远不会发生,因此你看到 s
的当前值,在你的情况下是 1, 2
.
在控制台中打印 s.X 和 s.Y。这是
的第一篇s = new S(1, 2, false);
第二个赋值永远不会执行,因为抛出了异常。
在等号左侧的 S 赋值之前发生异常。
所以你的 catch 块写出了之前赋值的原始值。
大写S变量是Type,小s是实例。
结构构造函数作为方法实现,这些方法将正在构造的结构作为隐含的 ref
参数。在许多情况下,编译器会执行如下语句:
s = new StructType(4);
相当于
var temp = default(StructType);
StructType..ctor(out temp, 4); // Not possible with C# syntax
s = temp;
然而,在某些情况下它不会这样做,而是简单地这样做:
StructType..ctor(out s, 4);
这可能是可以观察到的,尤其是在与其他语言编写的代码交互时,这些代码不支持 C# 用于标记 out
参数的属性。
例如,虽然不可能在 C# 中编写 IDictionary.TryGetValue
的实现,它不会将 default(TValue)
存储到其 out
参数,但该参数将被看到由其他语言作为 ref
参数;因此,用另一种语言编写的实现可能 return 而无需向其写入任何内容。如果结构构造函数将 this
传递给传入 IDictionary
的 TryGetValue
方法但不执行任何其他操作,则可以观察到结构构造的实际行为。