64

どうやら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;
}

この機能は、 C#第4版を介したJeffreyRichterのCLRの例で見つかりました。
1)どうやらそれはC#仕様にあります。

4

3 に答える 3

54

良い質問!

値型は、定義上、値によってコピーされます。this実際に保管場所のエイリアスではなかった場合、コンストラクターは、初期化する予定の変数を初期化するのではなく、コピーを初期化することになります。これにより、コンストラクターの有用性がかなり低下します。メソッドについても同様です。はい、変更可能な構造体は悪ですが、変更可能な構造体を作成する場合はthis、その値のコピーではなく、変更される変数である必要があります。

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

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

this受信者のストレージへのエイリアスの作成を回避する代替設計はthis、短期ストレージプールを割り当て、ctorで初期化してから、値で返すことです。このアプローチの欠点は、コピーの省略の最適化がほとんど不可能になり、ctorsとメソッドが奇妙に矛盾することです。

于 2013-02-08T08:51:10.783 に答える
10

また、ドキュメントが見つかりませんでした。

C#仕様を調べてみましたか?私はそれに関するドキュメントを見つけることができるので(7.6.7):

  • 構造体のインスタンスコンストラクター内のプライマリ式thisで使用される場合、変数として分類されます。変数の型は、使用法が発生する構造体のインスタンス型(§10.3.1)であり、変数は構築される構造体を表します。構造体のインスタンスコンストラクターの変数は、構造体タイプのパラメーターとまったく同じように動作します。特に、これは、変数がインスタンスコンストラクターのすべての実行パスで確実に割り当てられる必要があることを意味します。thisout

  • 構造体のインスタンスメソッドまたはインスタンスアクセサー内のプライマリ式thisで使用される場合、変数として分類されます。変数の型は、使用法が発生する構造体のインスタンス型(§10.3.1)です。

    • メソッドまたはアクセサーがイテレーターでない場合(§10.14)、変数はメソッドまたはアクセサーが呼び出された構造体を表し、構造体タイプのパラメーターthisとまったく同じように動作します。ref
    • メソッドまたはアクセサーがイテレーターの場合、変数は、メソッドまたはアクセサーが呼び出された構造体のコピーを表し、構造体タイプのパラメーターthisとまったく同じように動作します。

そのユースケースに関しては、すぐに多くのことを考えることはできません-コンストラクターで割り当てたい値の計算にコストがかかり、キャッシュされた値があるかどうかだけがわかりますにコピーしたいthis場合は便利かもしれません。

于 2013-02-08T07:15:43.080 に答える
0

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

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

この動作のために、可変構造体を「悪」と呼ぶ人もいますが、唯一の悪点は、C#もvb.netも、構造体のメンバーまたはプロパティが呼び出し不可能なものに対して呼び出し可能かどうかを示す属性を定義していないという事実です。によって直接渡されrefます。

于 2013-02-10T01:28:51.367 に答える