2016-01-12 20 views
61

私は自動化されたプロパティを作成しました:ゲッター付きの自動プロパティを設定することはできますか?

public int Foo { get; } 

は、これが唯一のゲッターです。 しかし、私は、コンストラクタを構築するとき、私は値を変更することができます

public MyClass(string name) 
{ 
    Foo = 5; 
} 

をなぜこれが取得するだけであっても、可能ですか?

+0

を実際にセッターを使用していません(それは1つを持っていないので)。これは、直接それが** **設定/初期化することはできません場合は、財産であるものを使用します(プロパティ名を使用する必要がある理由である私たちから隠されている、)基本となるフィールド –

+10

を設定しますか?ヤコブマサドはそれに完全に答えました – Vikhram

答えて

81

これは、また、このMSDN magazine article 'C# : The New and Improved C# 6.0' by Mark Michaelisにし、C# 6.0 draft Language Specificationで説明したように、「プロパティ読み取り専用のための自動プロパティの初期化子」として知られる「ゲッターのみの自動プロパティ」、新しいC#6の機能です。

読み取り専用フィールドのセッターは、コンストラクターでのみアクセスできます。他のすべてのシナリオでは、フィールドは引き続き読み取り専用で、以前と同じように動作します。

これは、入力が必要なコードの量を減らし、値を保持するためにプライベートモジュールレベルの変数を明示的に宣言する必要性を排除するための便利な構文です。

C#3のオートインプリメンテッドプロパティの導入以来、変更可能なプロパティ(ゲッターとセッターを持つプロパティ)は、変更できないプロパティ(ゲッターのみを持つプロパティ)よりも速く書けるようになっています。これは、読み取り専用プロパティに通常必要なバッキングフィールドのコードを入力する必要がないように、変更可能なプロパティを使用するように誘惑されていたことを意味します。 relevant section of the Microsoft C# Programming Guideには、自動実装プロパティの説明があります。次のように

This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sextonは良い説明と例を持っている:

前あなたは、読み取り専用(不変)プロパティを望んでいた場合、あなたは は、典型的には、読み取り専用バックフィールドを使用したいC#6.0に以下のように、 コンストラクタで初期化されます。 C#6.0では

public class Dog 
{ 
    public string Name { get; set; } 

    // DogCreationTime is immutable 
    private readonly DateTime creTime; 
    public DateTime DogCreationTime 
    { 
     get { return creTime; } 
    } 

    public Dog(string name) 
    { 
     Name = name; 
     creTime = DateTime.Now; 
    } 
} 

、あなたは 読み取り専用プロパティを実装するために、自動実装プロパティを使用することができます。これは、自動プロパティー イニシャライザーを使用して行います。結果は上記の例よりもはるかにクリーンです。 は、バッキングフィールドを明示的に宣言しなければなりませんでした。

public class Dog 
{ 
    public string Name { get; set; } 

    // DogCreationTime is immutable 
    public DateTime DogCreationTime { get; } = DateTime.Now; 

    public Dog(string name) 
    { 
     Name = name; 
    } 
} 

詳細はまたthe dotnet Roslyn repo on GitHubで見つけることができます:

自動プロパティが今セッターなしで宣言することができます。

ゲッター専用の自動プロパティのバッキングフィールドは、暗黙的に が読み取り専用として宣言されています(これは、反映のためのものですが、 の目的のみです)。上記の例のように、 プロパティのイニシャライザで初期化することができます。また、ゲッターのみのプロパティは 基になるフィールドに直接割り当てる 値を起こし宣言する型のコンストラクタ本体、中に割り当てることができます

これは、より簡潔なタイプを表現についてですが、そのことがまた注意します は、変更可能なタイプと 不変タイプの言語の重要な違いを取り除きます。自動プロパティは、 クラスを変更可能にしたい場合にのみ利用できる略式であり、従って誘惑は になりました。現在、ゲッターのみの自動プロパティでは、 競技場は可変と不変の間で水平になっています。

C# 6.0 draft Language Specificationで:

自動的に実装プロパティ

アン自動的に実装プロパティ(または短期の自動性)、 非抽象非のextern性のありますセミコロンのみのアクセッサー ボディ。自動プロパティにはアクセサを取得する必要があり、オプションで にアクセサを設定できます。プロパティは 、隠されたバッキングフィールドは、プロパティのために自動的に使用可能である 、自動的に実装プロパティとして指定され、アクセッサが読み出さその バッキングフィールドに書き込むために実装され

。自動プロパティにアクセサーが設定されていない場合、裏側の フィールドは読み取り専用とみなされます(読み取り専用フィールド)。読み取り専用の フィールドのように、囲みクラスのコンストラクタの本体 にゲッター専用の自動プロパティを割り当てることもできます。このような割り当てでは、プロパティの読み取り専用のバッキングフィールドに直接 が割り当てられます。

auto-propertyには、variable_initializer (変数の初期化子)としてバッキングフィールドに直接適用される というproperty_initializerがオプションで含まれることがあります。

+0

これは馬鹿なデザインです。プロパティが読み取り専用とみなされる場所に設定されている場合、これはコンパイル時エラーになります。 – Shiv

22

これは読み取り専用のプロパティを作成し、(あなたがそれらを宣言するとき、またはインライン)コンストラクタから値を初期化することができますa new feature in C#6です。

コンストラクタの外でこのプロパティの値を変更しようとすると、コンパイルエラーが発生します。

読み取り専用です意味であなたは、その値(インラインまたはコンストラクタの内部)を初期化したら、あなたはその値を変更することはできません。

+0

それでは、説明は何ですか?ゲッターの定義は何ですか?それは完全に真 –

+1

、プロパティのみを読み込むには、あなたのコード内でいくつかの条件をカプセル化するために非常に便利です。声明とほぼすべてのコード場合は、他のプロパティまたは条件を評価し、適切な値に、プロパティ – pseudoDust

4

C#3.0リリース中に自動プロパティ機能が言語に追加されました。バッキングフィールドなしでプロパティを定義することができますが、コンストラクタを使用してこれらの自動プロパティをデフォルト以外の値に初期化する必要があります。 C#6.0を使用すると、以下のようなコンストラクタをせずに、これらのプロパティを初期化することを可能にする自動プロパティ初期化子と呼ばれる新機能が導入されました:あなたは自動プロパティを使用してオブジェクト を作成し、ANを初期化したい場合は

以前は、コンストラクターが必要です以下のような デフォルト以外の値に自動プロパティ:

C#6.0で今
public class MyClass 
{ 
    public int Foo { get; } 

    public Foo(int foo) 
    { 
     Foo = foo; 
    } 
} 

、自動プロパティ で初期化子を使用する機能にはexpliciを意味しませんtコンストラクタコードが必要です。

public string Foo { get; } = "SomeString"; 

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" }; 

You can find more information on this here

10

それはコンストラクタ(または自動プロパティ初期化子)からの読み取り専用プロパティを初期化することができなかった場合は、必ず戻ってくるから、それは、役に立ちません型のデフォルト値(数値は0、参照型はnull)。すべてのC#バージョンのreadonlyフィールドに同じセマンティクスが適用されています。真ゲッターのみのプロパティを定義するには

(つまり、コンストラクタから初期化することはできません)、あなたはそれが定義の一部として返すかを指定する必要があります:C#6で

public int Foo { get { return 5; } } 

それとも、もっと簡潔に:

public int Foo => 5; 
+0

読み取り専用フィールドと同じではありません – sebagomez

+1

@sebagomezを読むたびに返すように書くことができます:私はあなたのポイントを取得していますかわからない - それがない何私は私の例で実証された? – Douglas

1

readonlyと宣言された変数は、コンストラクタ内で記述できますが、その属性を優先する言語では、コンストラクタが復帰した後に変更することはできません。その修飾子は、コンストラクタのパラメータに基づいて値が変化するフィールド(コンストラクタが開始される前に初期化できないことを意味しますが、コンストラクタが復帰した後に変更する必要はないフィールド)で必要となることが多いため、フィールドとして公開される変数にのみ使用できます。 readonly - 修飾されたフィールドのセマンティクスは、多くの場合、クラスではなく、不変のものであっても、フィールドではなくプロパティとしてメンバーを公開する方がよいことを除いて、パブリックメンバーにとって完璧です。

通常のフィールドと同じようにクラスが変更可能なプロパティを簡単に公開できるように、読み書き可能な自動プロパティが存在するように、読み取り専用の自動プロパティが存在するため、クラスにはreadonly修飾フィールドと同じように簡単に不変プロパティが公開されます。 readonlyと同様に、修飾されたフィールドはコンストラクタに書き込むことができます。get-onlyプロパティも同様です。

3

「読み取り専用自動実装プロパティ」私は

public string FirstName { get; } 

のようなプロパティはこれを確認するには、「読み取り専用自動実装プロパティ」

として知られていることを明確にしたいすべての

ファースト&上記のコードをVisual Studioで確認してください。言語バージョンをC#6.0からC#​​5.0に変更すると、コンパイラは次の例外をスローします 'readonly automatically implementedプロパティ'はC#5では使用できません。言語バージョン6以上を使用してください。

は、今私はあなたの2番目の質問

に来ていますC#言語のバージョン訪問here

を変更するには、「これが唯一のゲッターです。しかし、私はコンストラクタを構築するときに、値を変更することができます "

マイクロソフトでは、読み取り専用のロジックに「読み取り専用で自動的に実装されるプロパティ」を導入しています。キーワード "readonly"はC#1.0から入手できます。フィールド上の修飾子として "readonly"キーワードを使用し、同じクラスのコンストラクタでまたはの宣言時に に割り当てることができます。

public string FirstName { get; } = "Banketeshvar"; 

ウェイ2(中:「読み取り専用自動的に実装プロパティ」の同様の値で

は、2つの方法

ウェイ1(宣言時)に割り当てることができ

Person() 
{ 
FirstName = "Banketeshvar"; 
} 

あなたは純粋にReadOnlyプロパティを探しているなら、今あなたは、コンストラクタから「フルネーム」properyの値を代入することはできません。この

public string FullName => "Manish Sharma"; 

のために行くのプロパティ

純粋に読み取り専用。 あなたはそれが、次の例外

スローされますことを実行しようとした場合、「プロパティまたはインデクサは 『Person.FullName』に割り当てることはできません - それは読み取り専用です」

関連する問題