2016-05-28 2 views
0

C#で不変な型があります。それらは基本的にすべてちょうどです。不変型のコンストラクタの略語

public class Class : IInterface 
{ 
    public Class(IInterface2 prop1, IInterface2 prop2) 
    { 
     Property1 = prop1; 
     Property2 = prop2; 
    } 

    public IInterface2 Property1 { get; } 
    public IInterface2 Property2 { get; } 
} 

コンストラクタ内の2つのプロパティセットが混在したバグが見つかりました。

このコンストラクタを省略または生成できるC#の不変型の略語はありますか?

このよう

var f = new Class { Property1 = null, Property2 = null }; 

として残念ながら

public class Class : IInterface 
{ 
    public readonly IInterface2 Property1; 
    public readonly IInterface2 Property2; 
} 

、私はそれを使用しようとすると、コンパイラは、にもかかわらず、読み取り専用のフィールドは、コンストラクタや変数の初期化子を除いて設定することができないと言って、私に叫びますそれは明らかに恐ろしい変数初期化子であるという事実。

+0

.NETのコンパイラにバグがありますか? –

+0

さて、私は、このような方法では読み取り専用フィールドを設定することはできないことを仕様上見落としていると推測します。 – Puppy

+0

コンパイルエラーが表示されますか? C#6以前のバージョンを使用していますか? –

答えて

2

いいえ、クラスの外側または読み取り専用プロパティを設定できる構文はありません。

イニシャライザの構文は、プロパティセット呼び出しのシンタックスシュガーです。これは、想定される動作であり、仕様上の監視ではありません。続いコンストラクタを呼び出すことなく、

Object and Collection Initializers (C# Programming Guide)

オブジェクト初期化子を使用すると、任意のアクセス可能フィールドまたは作成時にオブジェクトのプロパティに値を代入してみましょう:これは、MSDNの記事次Readonly field in object initializer問題で議論されの代入文の行

+0

実際に初期化するためにイニシャライザの構文を修正する必要があるようです。ここで重要な部分は「作成時」です。 – Puppy

+0

@Puppyあなたが望む機能のためにまともな仕様を思いついてみることは、常に良い練習です。もしあなたがそれを試してみるなら、プロパティはフィールドではないことを忘れないでください。同時に、オブジェクトの外側から 'set'プロパティを使うことができないと同時に初期化子の構文を許さない方法が必要です。 –

1

「読み取り専用フィールドには、それが明確に田舎者の白人野郎変数 初期化子だという事実にもかかわらず、コンストラクタまたは変数 初期化子以外で設定することはできません。」

いいえ、そうではありません。 「変数初期化子が」これです:あなただけの定義の同じ場所に変数を初期化しているので

public class Class 
{ 
    public int Property1 { get; } = 5; 
} 

「​​」は、変数初期化子です。

this articleを参照してください。

あなたが「変数初期化」を呼んでいるが実際のためだけ糖衣構文である「オブジェクト初期化」、である:

  • がOUTSIDE CONSTRUCTORのリストを設定コンストラクタを呼び出す

    1. プロパティの。たとえば、

    var c = new Class("hello", 4.5) //<-- this is the constructor 
    { 
        Prop1 = new DataTable(), //<-- from here you're outside the constructor, 
        Prop2 = new Point(2,3), // so you can't set an only "{ get; }" property. 
        Prop3 = 0.2, 
    }; 
    
  • 1

    私が正しくあなたを理解していれば、互換性のある2つのタイプのコンストラクタが呼び出された場合は、読み取り専用フィールドを初期化することができるようにしたい理由は混同を避けるためです間違った順序で、右か?

    これは現在できない理由がうまく説明されていますが、同じコンストラクタ(named arguments)を使用しながらこの問題を最小限に抑えるのに役立つテクニックがあります。 C#のは、明示的にパラメータの名前を述べ、その後、任意の順序でそれらを指定することができます:

    var myClass = new Class(prop2: interface2Instance, prop1: interface1Instance); 
    

    これは、コンパイル、そしてどのようなパラメータに渡されたどのような値に明確になるであろう。

    もちろん、コード自体にこの要件を適用することはできませんが、明確化が必要な互換性のある型を持つコンストラクタが多数ある場合は、になります。