2009-07-13 10 views
11

私は次のコードをお持ちの場合:プライベートコンパイラで生成された変数はセッターのために作成されプライベート-setterプロパティ

public class MyClass 
{ 
    public string myName { get; private set; } 
    public string myId { get; set; } 
} 

を。私はsetterがオブジェクトの初期化のためだけにアクセスできないようにしたい。しかし、myName変数を最初に設定するにはどうすればよいですか?オブジェクトの初期化について読ん

は、私は、次を発見した:

...それは読み取り専用と 基礎となるストレージを表す プライベートフィールドは、私たちが使用することはできません コンパイラが生成した名前を持っていますコンストラクタを使用して を割り当てます。ソリューションが使用することです[...]オブジェクト初期化子

ソリューションを使用するように、そして、次のようになります。

MyClass mc = new MyClass { 
myName = "What ever", 
myId = "1234" 
}; 

しかし、このことをコトコンパイラエラーで終わる:

setアクセサーにアクセスできないため、プロパティまたはインデクサが 「MyClass.MyClass.myName」 は、この文脈で使用することはできません

オブジェクトの初期化を使用してこの値を設定する方法はありますか?存在する場合、それを行う正しい方法は何ですか?

答えて

6

プライベートセットはあなただけで何かから(セット)それを初期化できることを意味しますMyClassのメンバー。たとえば:

 public class MyClass { 
     public string myName { get; private set; } 
     public string myId { get; set; } 

     public static MyClass GetSampleObject() { 
      MyClass mc = new MyClass 
      { 
       myName = "Whatever", 
       myId = "1234" 
      }; 
      return mc; 
     } 
    } 

(私はコピーしてGetSampleObjectメソッドに初期化コードを貼り付け)。

MyClassの外に設定しようとすると、プライベートはプライベートであるため、コンパイラエラーが発生します。

12

いいえこれを達成する方法はありません。オブジェクトイニシャライザは、イニシャライザの外部からアクセス可能なフィールドとプロパティにのみアクセスできます。

これらのプロパティを明示的に設定するコンストラクタを使用することをお勧めします。

+0

ありがとう、私は3.0の新機能を使用してこれを達成できるかどうかを学生に見せたいと思っていましたが、答えはノーと思われます。今私は引用符を持っている本の正誤表を提出する必要があります:P – jluna

5

彼らは、私はこの過去のint型の要件としても用OR/Mのものを持っていたコンストラクタ

+1

はい、なぜ簡単なことを複雑にするのですか? –

+0

オブジェクトの初期化中に何かしたい場合は、コンストラクタで行います。それ以外のところでやることは理にかなっていません。 –

+0

これは学業目的のためのものです。私は学生にC#3.0の新機能を見せているし、プロパティとオブジェクトの初期化でいくつかのテストをしています。私はこの質問を受け取りました。 本書(私が引用したところ)はそれができると言いましたが、テストはできなかったことを示していましたので、私は尋ねることにしました。 – jluna

1

への引数として渡す検討する初期化時に設定する必要がある場合。私が基本的にやっていることは、バッカーフィールドで実際のプロパティを使って、プロパティが既に設定されているかどうかを調べることです。その場合は、例外をスローします。

public string myName 
{ 
    get{ return _myName; } 
    set 
    { 
     if(_myName != null && _myName != value) 
      throw new Exception("The myName property may only be set once."); 
     _myName = value; 
    } 
} 

private string _myName; 

そしてまた、コンストラクタの初期化を活用するOR/M互換性のために別のオプション:がmyName

public class MyClass 
{ 
    [Obsolete("For ORM use only!")] 
    [EditorBrowsableState(EditorBrowsableState.Never)] 
    public MyClass(){} 

    public MyClass(string name){ myName = name; } 

    public string myName { get; private set; } 
    public string myId { get; set; } 
} 
+2

このコードを使用するすべての人と確立されたこの種のことについて非常に明確な慣習がない限り、これに対して警告します。私がセッターを持つ財産を見ると、私は値を設定するためにそれを使うことができると思います。それが期待していないときに例外をスローすると本当に私を苛立たせるでしょう。 –

+1

確かに...これは、ORMのPKフィールドのような不変フィールドの場合には意味があります。 –

+0

一度だけ設定される(つまり初期化される)不変フィールドは、コンストラクタで初期化することができます。 –

関連する問題