簡體   English   中英

C#結構“ this =…”

[英]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參數完全相同。

    • [關於迭代器的文字]

如果s1s2Foo類型的結構,具有字段f1f2f3 ,則語句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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM