web-dev-qa-db-ja.com

値タイプの「this」変数を変更する

どうやらthisの値は、構造体のどこからでも変更できます(ただしクラスでは変更できません)。

struct Point
{
    public Point(int x, int y)
    {
        this = new Point();
        X = x; Y = y;
    }
    int X; int Y;
}

私はこれを以前に見たことも、必要としたこともありません。なぜそんなことをしたいのでしょうか? Eric Lippertが思い出させる 機能を実装するには正当化する必要があること。これを正当化できる優れたユースケースは何ですか?これが非常に貴重なシナリオはありますか? ドキュメントが見つかりませんでした1

また、コンストラクターを呼び出すための既知の代替構文が既に存在するため、この機能が冗長になる場合があります。

public Point(int x, int y)
    : this()
{
    X = x; Y = y;
}

私はこの機能をJeffrey Richterの例 CLR via C#4th edition の例で見つけました。
1)どうやら C#仕様 の中にあります。

良い質問!

値タイプは、定義により、値によってコピーされます。 thisが実際には格納場所のエイリアスではなかった場合、初期化する変数を初期化するのではなく、コンストラクタはコピーを初期化しますです。これはコンストラクタをあまり役に立たないでしょう!そしてメソッドについても同様です。はい、変更可能な構造体は悪ですが、もう一度変更可能な構造体を作成する場合、thisは、その値のコピーではなく、変更される変数でなければなりません。

説明する動作は、その設計決定の論理的な結果です。thisは変数にエイリアスを設定するため、他の変数に割り当てることができるのと同じように、変数に割り当てることができます。

フィールドに割り当てるのではなく、thisに直接割り当てるのは少し奇妙です。 thisに直接割り当てて、その割り当ての100%を上書きするのはさらに奇妙です!

thisを受信側のストレージのエイリアスにすることを回避する代替設計は、短期ストレージプールからthisを割り当て、それをctorで初期化してから、値で返すことです。そのアプローチの欠点は、コピー省略最適化がほとんど不可能になり、また、アクターとメソッドに奇妙な一貫性がなくなることです。

54
Eric Lippert

そのタイプのパブリックフィールドとプライベートフィールドで構成されるストレージロケーションの集合における値タイプのストレージロケーション。値型を通常の(値)パラメータに渡すと、そのすべてのフィールドの内容が物理的および意味的に渡されます。値の型をrefパラメータとして渡すと、意味的にはすべてのフィールドの内容が渡されますが、1つの「byref」を使用してすべてのフィールドが渡されます。

構造体でメソッドを呼び出すことは、構造体(およびそのすべてのフィールド)をrefパラメータとして渡すことと同じです。ただし、1つのしわを除きます。通常、C#もvb.netも読み取り専用の値を許可しませんrefパラメータとして渡されます。ただし、どちらの方法でも、読み取り専用の値または一時的な値に対してstructメソッドを呼び出すことができます。これは、すべての構造体(およびそのすべてのフィールド)のコピーを作成し、そのコピーをrefパラメータとして渡すことによって行われます。

この動作のため、一部の人々は可変構造体を「悪」と呼んでいますが、C#もvb.netも属性を定義していないため、構造体のメンバーまたはプロパティが、 refから直接渡される。

0
supercat