2010-11-25 10 views
2

プライベートな読み取り専用フィールドをクラス内のどこにでも割り当てることができる方法はありますか?コンストラクタの外に値を割り当てることができるReadonlyフィールド

つまり、プライベートな読み取り専用のフィールドを探していますが、これは値を1回だけ割り当てることができますが、必ずしもコンストラクタ内にある必要はありません。そのため、値がフィールドに再割り当てされた場合、コンパイル時エラーが表示されます(あまりにも多くを求めていると確信しています)。

同じ仕事をする可能性のあるパターン(言語機能ではない)がある場合は、それを知ることに本当に関心があります。

ありがとうございます。

答えて

1

短い答えはノーです。コンパイラがチェックされている1回限りの割り当てを持つことができる唯一の場所はコンストラクタです。あなたは割り当てが複数回試行された場合は、実行時エラーを取得したいシステムを作成することもできますが、あなたは、プロセスを自動化するための一般的な構造体を作成することができ、この

4

コンパイル時エラーは発生しませんが、プロパティで探しているものを達成できます。 setterでは、内部bool/flagがfalseの場合にのみ値を設定します。最初に設定したら、フラグをtrueに設定します。セッターは、コードの別の部分で再び呼び出された場合と、あなたは彼らがすでに

private bool fieldAlreadySet = false; 
private string field; 

public string Field 
{ 
    get {return field;} 
    set 
    { 
     if (fieldAlreadySet) throw new InvalidOperationException("field already set"); 
     this.field = value; 
     fieldAlreadySet = true; 
    } 
} 
0

あなたはそれが割り当てられたかどうかをチェックし、私有財産を使用することができます初期化されている知っているようにと、InvalidOperationExceptionをスローすることができますし、それがされていない場合にのみ値を割り当てます。

int? _writeOnceField; 

private int? WriteOnce 
{ 
    set 
    { 
     if (!_writeOnceFiled.HasValue) 
     { 
     writeOnceFiled = value; 
     } 
     else 
     { 
     // Throw exception 
     } 
    } 
} 
0

言語サポートはありませんが、希望の動作を実装した設定ツールを作成することができます。明らかに、それはあなたが時間エラーをコンパイルすることはできませんが、おそらくあなたが行うことができる最高の言語サポートなしに。

1

を行うにはC#の構文はありません。

public struct WriteOnce<T> 
{ 
    private T? _value; 

    public T Value 
    { 
     get { return _value; } 
     set 
     { 
      if (_value.HasValue) throw new InvalidOperationException(); 
      _value = value; 
     } 
    } 
} 

編集 私はちょうど上記がコンパイルされないことに気付きました。コンパイラは_valueの型をNullableにすることはできません.T in Nullableはnull不可能な型でなければならないからです。 - それはうまく機能しないことが、私はそれがより良い仕事と述べ

public struct WriteOnce<T> 
{ 
    private T _value; 
    private bool _hasValue; 

    public bool HasValue { get { return _hasValue; } } 

    public T Value 
    { 
     get { return _value; } 
     set 
     { 
      if (HasValue) throw new InvalidOperationException(); 
      _value = value; 
      _hasValue = true; 
     } 
    } 

    public static implicit operator T(WriteOnce<T> x) 
    { 
     return x.Value; 
    } 

    public WriteOnce(T val) 
    { 
     _value = val; 
     _hasValue = true; 
    } 
} 

注:

はここで少し良く動作する実装です。

最初に、何かを割り当てずに使用しようとしていることを検出すると、コンパイラはそれに気付きます。そのようにそれを初期化することの世話をします。

WriteOnce<int> foo = default(WriteOnce<int>); 

第二に、それは変更に例外をスローした場合でも、C#がまだ喜んであなたがそれを上書きできるようになります。したがって、これは機能の一部をカプセル化しますが、それがオブジェクトのインタフェースで公開されることになる場合、誤用を防ぐためにプロパティにラップする必要があります。

private WriteOnce<int> _someInt = default(WriteOnce<int>); 
public int SomeInt 
{ 
    get { return _someInt; } 
    set { _someInt.Value = value; } 
} 

しかし、それはまだ本当に私が変更可能な構造体を作成したオリジナルのスニペットにコミット最後の悪質なエラーを回避しません。このようなことをたくさんしている場合は、かもしれないは、自分自身を繰り返さないためにその原則に違反する価値がありますが、これは間違いなく慎重にコメントし、公開されているインターフェイスから守らなければならない潜在的な罠です。

しかし、一度限りのものであれば、プロパティを直接実装することについて他の人が示唆していることは、それほど複雑ではなく、より安全です。

0

これは、宣言の代入やシングルトンの候補のように見えます。

public class SomeClass { 
    private readonly Type t = typeof(SomeClass); 
} 

そうでなければ、言われた他の人のように、セッターだけで内部的なプロパティを作り、それに値を割り当てます。

public class SomeClass { 
    private Type t; 

    internal Type Type { 
     set { 
      if (t == null) t = value; 
     } 
    } 
} 
0

私はそれがコンストラクタで行われた場合、それを行う方法を達成したと思います。また、変数宣言行に記述することもできます。 これらのコンテキスト外で行わ場合は、エラーが表示されます:読み取り専用フィールドには、(コンストラクタまたは変数初期化子を除く)に割り当てることはできません

public class BillLine 
{ 
    public BillLine(Bill bill) 
    { 
     m_Bill = bill; 
    } 

    private readonly Bill m_Bill; 

    public Bill Bill 
    { 
     get { return m_Bill; } 

     //supposed to be set only in the constructor 
    } 

    //(...) 
} 
+0

この投稿について申し訳ありませんが、私は「外部への注意を払っていませんコンストラクタ "タイトルの一部。 – sergiol

関連する問題