web-dev-qa-db-ja.com

構造体を初期化する方法は?

次の割り当てを可能にするために、任意の構造にどのメンバーを実装する必要がありますか?

public struct MyStruct {
   String s;
   Int length;
}

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 };

// Now, I want the following code to set the 's' to "Lol" and the
// length to 3 (length of "Lol"). The second part should be done
// automatically.
myStruct = "Lol"; // Or myStruct = String("Lol");

これをどのように行う必要がありますか?

53
Yippie-Ki-Yay

文字列値を構造体値に変換する暗黙的な演算子を使用します。

public struct MyStruct {
  public string s;
  public int length;

  public static implicit operator MyStruct(string value) {
    return new MyStruct() { s = value, length = value.Length };
  }

}

例:

MyStruct myStruct = "Lol";
Console.WriteLine(myStruct.s);
Console.WriteLine(myStruct.length);

出力:

Lol
3
90
Guffa

構造型は、実用的な場合、すべての状態をパブリックフィールドにカプセル化して、それぞれの型に有効な値に個別に設定するか、コンストラクター、ファクトリーによってのみ設定できる単一の統一値として動作する必要があります、メソッド、または明示的なrefパラメーターとして構造体のインスタンスをそのパブリックメソッドの1つに渡すことによって。一部の人々が主張していることとは反対に、パブリックフィールドを持つ構造体は、個々に操作されるかグループとして渡される(ポイントの座標など)賢明な値のセットを表すことになっている場合、何も問題はありません。歴史的に、パブリックプロパティセッターを持つ構造には問題があり、パブリックフィールド(代わりにセッターを使用する必要があることを意味する)を避けたいという欲求により、一部の人々は、可変構造を完全に避けるべきであると示唆しましたが、フィールドにはありませんプロパティにあった問題。実際、露出フィールド構造体は、独立した変数の緩やかなコレクションの理想的な表現です。なぜなら、is単なる緩やかな変数コレクションだからです。

ただし、特定の例では、構造体の2つのフィールドはおそらく独立していないはずです。構造体を適切に設計するには、次の3つの方法があります。

  • パブリックフィールドのみを文字列にして、lengthという読み取り専用の「ヘルパー」プロパティを使用して、文字列がnullでない場合は長さを報告し、文字列がnullの場合はゼロを返すことができます。 。

  • 構造体にパブリックフィールド、プロパティセッター、または変更メソッドを公開せず、唯一のフィールド(プライベート文字列)の内容をオブジェクトのコンストラクターで指定することができます。上記のように、lengthは、格納された文字列の長さを報告するプロパティです。

  • 構造体にパブリックフィールド、プロパティセッター、または変更メソッドを公開せず、2つのプライベートフィールドを持つことができます。1つは文字列用、もう1つは長さ用で、どちらも文字列を取得して格納するコンストラクタで設定されます、その長さを測定し、保存します。文字列の長さを決定するのは十分に速いので、おそらく計算してキャッシュする価値はありませんが、文字列とそのGetHashCode値を組み合わせた構造を持つことは有用かもしれません。

ただし、3番目の設計に関する詳細に注意することが重要です:スレッドセーフでないコードにより、別のスレッドが書き込み中に構造体の1つのインスタンスが読み取られる場合、その構造体インスタンスが誤って作成される可能性がありますフィールド値に一貫性がありません。結果の動作は、クラスがスレッドセーフでない方法で使用される場合に発生する動作とは少し異なる場合があります。セキュリティに関係するコードは、構造フィールドが一貫した状態にあると想定しないように注意する必要があります。悪意のあるコードは、「完全信頼」環境であっても、その状態が一貫していない構造体を簡単に生成できるからです。やりたい.

[〜#〜] ps [〜#〜]-文字列からの割り当てを使用して構造を初期化できるようにする場合は、暗黙の変換演算子を使用してLengthは、基になる文字列の長さがnull以外の場合、または文字列がnullの場合はゼロを返す読み取り専用プロパティです。

9
supercat
  1. 「長さ」は「s」の実際の長さから逸脱します。答えがいいえの場合、文字列はすでに長さを保存しているので、長さを保存する必要はありません。s.Lengthを呼び出すだけです。

  2. 要求した構文を取得するには、次のような「暗黙的な」演算子を実装できます。

    static implicit operator MyStruct(string s) {
        return new MyStruct(...);
    }
    
  3. 構造体を可変にするかどうかに関係なく、暗黙の演算子は機能します。

5

構造体にはメソッドとプロパティを含めることができます...試してみてください

public struct MyStruct { 
    public string s;
    public int length { return s.Length; }
}

Correction@Guffaの答えは、それが可能であることを示しています...詳細はこちら: http://www.codeproject.com/KB/ cs/Csharp_implicit_operator.aspx

1
Adam Spicer