2011-12-20 16 views
19

パブリックプロパティのセッターのアクセス修飾子をprivateからpublicに変更すると、それを参照する他のアセンブリに大きな変更が加えられますか?パブリックプロパティのアクセス修飾子を変更することは大きな変更ですか?

+0

いいえ、他のアセンブリは以前はこのプロパティを使用できませんでした。 –

+0

@Hans、プロパティのゲッターは公開されているため、他のアセンブリでも使用できます。 – mkus

+0

さて、あなたはゲッターを変更していませんか? JITコンパイラは、変更されたプロパティ宣言に問題はありません。 –

答えて

31

更新This question was the topic of my blog in January 2012。素晴らしい質問をありがとう!


私は「破壊の変化」によって、あなたが意味することを前提とし、「私は、このアセンブリに依存するコードを再コンパイルするとき、コンパイルまだコンパイルするために使用されるコードのでしょうか?」

厳密に言えば、以前はプライベートであったプロパティーセッターをパブリックにすることは大きな変化です。

// Assembly Alpha 
public class Charlie 
{ 
    public int P { get; private set; } 
} 
public class Delta 
{ 
    public int P { get; set; } 
} 

そしてアルファを参照する別のアセンブリに:

// Assembly Echo 
class Foxtrot 
{ 
    static void M(Action<Charlie> f) {} 
    static void M(Action<Delta> f) {} 
    static void Golf() 
    { 
     M(y=>{y.P = 123;}); 
    } 
} 

あなたはアセンブリエコーをコンパイルあなたはこのコードを持っていると仮定します。クラスFoxtrotには、Mで過負荷解決を行うメソッドGolfがあります.Mには2つのオーバーロードがあります。チャーリーの行動を取る人とデルタの行動をとる人。ラムダパラメータyがチャーリー型の場合、ラムダボディはアクセシビリティエラーを生成するため、Mのオーバーロードは適用可能な候補ではありません。オーバーロードの解像度で2番目のオーバーロードが選択され、コンパイルが成功します。

これで、Charlie.Pの設定者が公開されるようにアセンブリAlphaを変更しました。エコーを再コンパイルします。 Mの両方のオーバーロードが等しく有効で、どちらも他よりも優れていないため、オーバーロード解決エラーが発生します。アルファの変更により、エコーの編集が失敗します。 Alphaへの変更は大きな変化でした。

質問は「これは急変ですか?」明らかにそうです。ほとんどすべての変更は何らかの種類の急激な変化です。問題は、実際に破損の変更が実際に誰かを中断させるかどうかであり、そうであれば、新機能の利点と比較して休憩を修正するコストはいくらですか?

+2

ブラボーには何が起こったのですか? – kvb

+20

@kvb:予約を変更するために航空会社に連絡しなければなりませんでした。問題の場合は、確認番号が表示されます:153ADN6、1-5-3-Alpha-Dog-November- 6 "、と私は言った"ありがとう、デルタは、Dの国際的な無線コードの単語ですか? "彼女は言った "*私たちはこの航空会社でその言葉を言っていない!*"私はあなたに言います。起動する国際ラジオのアルファベットを知っているスマートで面白い人を得ることはまれです。 –

+2

あなたが実際に電話していたデルタだったのであれば、もっとおかしくなるでしょう。 –

5

これは、「変更を壊す」ことにどれくらい厳格にしたいかによって決まります。

1つの定義は、参照コードのビルドまたは実行を中断しますか。

もう1つは、変更したと他のコードが判断できるかどうかです。

最初の定義では、これは大きな変更ではありません。 2番目の定義では、それは大きな変化です。

+1

[Ericの答え](http://stackoverflow.com/a/8581029)と[Jeffrey's Answer](http://stackoverflow.com/a/8581019)は、コンパイルを中断するエッジケースを提供しています。 – Brian

0

私は思っていませんが、あなたはこのセッターをプライベートにする知恵があるのか​​知っているはずです。 アクセス修飾子は、ライブラリのコンシューマとカプセル化にとって重要です。

3

これらの他のアセンブリが反射を使用してセッターの存在をテストしている可能性があります。

しかし、初期バインドされたコードは壊れません。

これはセマンティクスの変更かどうかを検討するもう1つのことです。プロパティが以前建設中に設定されていて、いつでも変更できる場合は、値をキャッシュしたユーザーを壊して辞書キーなどとして使用する可能性があります。

2

プロパティの可視性が向上するため静的にリンクされたアセンブリや静的な参照には問題はないはずです。これらのアセンブリは、今まであなたのプロパティを読み取り専用として扱っていました。

一部のアセンブリでリフレクションを使用してプロパティーに関する情報を取得し、いくつかのアクションを実行すると、ここで発生する可能性のある唯一の問題はです。例えば

これはあなたが(実際のフレームワークから独立した)GridViewまたはListViewのように、いくつかのコントロールにをあなたのデータを表示するためにデータバインディングを使用し、それはこのことかもしれないビジネスオブジェクトのプロパティがある場合プロパティは現在「更新可能」と認識され、ユーザはこれまで不変であるとみなされた値(および他のアセンブリ)を変更する可能性があります。

17

これは、既存のコードがコンパイルされなくなる可能性があるという点で大きな変更です。

一部の言語では、表示されているすべてのアクセサをオーバーライドしないでプロパティをオーバーライドすることはできません。 VBはそのような言語です。

では、次のC#クラスを持っていると言う:

Class B : Inherits TestLibrary.A 
    Public Overrides ReadOnly Property X As Integer 
     Get 
      Return MyBase.X 
     End Get 
    End Property 
End Class 

お知らせ財産上のReadOnly修飾子:あなたのライブラリーを参照するVBプロジェクトで

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      private set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

、あなたはクラス定義を持っています。ゲッターを定義するだけなので、VBではこれが必要です。あなたは今、コンパイル時に取得します

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

:あなたのC#クラスにセッターからprivate修飾子を削除し、今

Property without a 'ReadOnly' or 'WriteOnly' specifier must provide both a 'Get' and a 'Set'.

:あなたはそれを残している場合は、コンパイル時にエラーが発生しますあなたのVBコードのエラー:あなたが変更を行った後、あなたのライブラリがコンパイルされませんので、それは破壊変化である参照

'Public Overrides ReadOnly Property X As Integer' cannot override 'Public Overridable Property X As Integer' because they differ by 'ReadOnly' or 'WriteOnly'.

同じコード。

+5

いいです!言語間の休憩は最も難しいのです。 –

+0

プロパティが実装される方法は本当に嫌いです。ネット; 3つのタイプのプロパティを持つことには本当にどのような利点がありますか?1つは、プロパティgetterとsetterを単純に構文の目的で表示、シリアル化などの目的で使用するいくつかの属性を持つメソッドにするのではなく、プロパティとして見なされるべきですか?ルーチンが 'Property '型のパラメータを受け入れることが可能であれば、getterとsetterを単一のエンティティとして束縛することにいくつかのメリットがありますが、そうではありません。だから、何がメリット? – supercat

+0

@supercatこれは、プロパティが.NETでどのように機能するかを示します。ILはプロパティを呼び出すことはなく、メソッドのみを呼び出します。プロパティは、メタデータのみに存在します。 getterメソッドとsetterメソッドが容易にアクセスできないという事実は、言語設計上の問題です。それらはパブリックメソッドですが、ほとんどの言語では「SpecialName」属性があるため隠されています。 C#が明示的にこれらのメソッドを呼び出すことを妨げる理由は分かりません。 –

関連する問題