[英]C# Structs “this = …”
我剛剛在反射器中瀏覽文件,並在struct構造函數中看到了這一點:
this = new Binder.SyntaxNodeOrToken();
我以前沒看過這個術語。 有人可以解釋一下此分配在C#中的含義。 對Google來說很難。
基本上,它將替換值。 它有效地將所有字段從右側復制到左側...除非它可以工作,即使這些字段是只讀的。 是的,它看起來確實很奇怪,而且有點嚇人。
例:
using System;
class Test
{
static void Main()
{
Point point = new Point(10, 20);
point.ReplaceWith(new Point(2, 3));
Console.WriteLine(point); // (2, 3)
}
}
struct Point
{
private readonly int x;
private readonly int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public void ReplaceWith(Point other)
{
this = other;
}
public override string ToString()
{
return string.Format("({0}, {1})", x, y);
}
}
有關更多信息,請閱讀C#4規范的7.6.7節,其中包括:
[有關其在struct構造函數中使用的文本]
當在實例方法或結構的實例訪問器內的主表達式中使用
this
變量時,它將被分類為變量。 變量的類型是發生用法的結構的實例類型。
如果方法或訪問器不是迭代器,則
this
變量表示為其調用了該方法或訪問器的結構,並且其行為與該結構類型的ref
參數完全相同。[關於迭代器的文字]
如果s1
和s2
是Foo
類型的結構,具有字段f1
, f2
和f3
,則語句s1 = s2
在語義上等效於
s1.f1 = s2.f1;
s1.f2 = s2.f2;
s1.f3 = s2.f3;
除了不應該假設賦值操作的順序(甚至讀和寫的相對順序;例如,所生成的代碼可能將所有三個字段讀入寄存器,然后再寫入所有三個字段)外,我們不做任何假設。 所有字段都將被復制,無論它們是公共的還是私有的,可變的或所謂的不可變的。 不會調用任何屬性獲取器或設置器; 源結構和目標結構都不會收到有關結構字段重復或覆蓋的任何通知。
聲明this = new Foo(whatever);
在C#(*)中等於
Foo temp;
call Foo's constructor (out temp, whatever);
this.f1 = temp.f1;
this.f2 = temp.f2;
this.f3 = temp.f3;
(*)vb.net中的Struct構造函數語義不同
如上所述,完成字段分配時無需考慮字段是公共字段還是私有字段,也無需考慮它們是否是不變的。
我認為(與其他人的看法相反)結構應該經常公開可變字段的原因之一是這樣的語法:
// Assume myKVP is a field of type KeyValuePair<Wizzle, int>
rr = new KeyValuePair<Wizzle, int>(myKVP.Key, myKVP.Value + 1);
使得myKVP
似乎在myKVP
后將引用與其之前持有的實例不同的實例,而實際情況是:
// Assumes backing fields are named _Key and _Value
// Note that C# won't allow one to write private fields directly, but the
// act of copying one struct instance to another copies all the fields,
// public and private, from the source instance to the destination.
KeyValuePair<Wizzle, int> temp;
temp._Key = myKVP.Key; // Constructor has access to backing fields
temp._Value = myKVP.Value+1;
myKVP._Key = temp._Key; // Struct assignment copies all fields, public and private
myKVP.Value = temp.Value;
換句話說,該語句不會使myKVP
報告到其他實例; the old instance by overwriting its fields with those of the new instance, and then discards the new instance. 相反,它創建一個新實例,通過用新實例的字段覆蓋舊實例來舊實例,然后丟棄新實例。 如果在執行上述分配時某些代碼正在評估myKVP.ToString()
,則該突變將影響正在打印的myMVP
實例。
結構可以具有有用的語義,但所謂的“不可變”結構則沒有。 , regardless of any semantics imposed by the type. 非瑣碎的結構(可以為其創建與默認值不同的值的結構)是可變的,並且僅當它們被保存在可變的 ,才不受類型強加的任何語義的影響。 . 自變異結構,即其結構變異this
在任何方法除了在構造函數和屬性setter,可以有一些意外行為,因為編譯器有沒有禁止的,這將發生變異等方法調用的方式this
不可變結構 。 但是,公開暴露於struct字段不會造成任何此類危險。 由於非平凡結構的可變實例的所有字段本質上都是可變的,因此無論該結構可能進行任何允許突變的嘗試,而且該結構的不可變實例的所有字段即使暴露也都是不可變的,因此該結構努力使其字段“不變”的做法實際上是在撒謊。 有時可能有用的謊言(例如,假設字段內容服從某些不變式),但沒有真正的原因就不應該說謊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.