2012-01-22 6 views
24
public class Demo 
{ 
    private List<string> _items; 
    private List<string> Items 
    { 
     get 
     { 
      if (_items == null) 
       _items = ExpensiveOperation(); 

      return _items; 
     } 
    } 
} 

他の方法が_itemsフィールドにアクセスする必要があります「は使用しないでください」と。アイテムを遅延ロードするプロパティを使用しているので、他の開発者が誤って_itemsフィールドを使用しようとすることはありません。C#のマーキングメンバー<code>Demo</code>クラスの

私が使用できるObsoleteAttributeがありますが、このフィールドは技術的に時代遅れではありません。

メンバーに「使用しない」とマークする良い方法はありますか?

+26

チームの開発者を信頼しない場合は、大きな問題があります。 – jason

+0

私はあなたがそれについて心配している場合は、抽象化の別の層の背後にあるアイテムを非表示にして、プライベートメンバーを一般的な使用から隠すことができると思います。 –

+19

プライベートです。そのお金はそこに止まります。複数の開発者がクラスのプライベートな部分で作業する場合、本当にうまく通信する必要があります。少なくとも夕食と映画。あなたが強制することのできるものではなく、あなたは良いデザインによってそれを避けることができます。 –

答えて

48

あなたがしたいことのための一般的なテクニックではありません(そして、他の回答がカバーするように、あなたは他の開発者を信頼する必要があります)、この例では、Lazy<List<T>> .NET 4以降 - それはバックポートするのは簡単ですが)

class Demo { 
    readonly Lazy<List<string>> _items; 
    public Demo() { 
     var _items = new Lazy<List<string>>(ExpensiveOperation); 
    } 
    List<string> Items { get { return _items.Value; }} 
} 

readonly /非可変のアプローチ一般的にバッキングフィールドのいずれかの方法のために行くための方法です。

EDIT:Timwiの答え@に基づいて(あなたのアイデアのような場合は+1を行く)1がそれに町に行くことができ、さらにはLazyフィールドを公開しないようにJavaScriptのstylee使用capability-based restrictionに、ただ操作がその上に閉じ(また@Mr失望のReadOnlyCollection提案を組み込ん):

class Demo { 
    readonly Func<ReadOnlyCollection<string>> _getItems; 
    public Demo() { 
     var items = new Lazy<List<string>>(ExpensiveOperation); 
     _getItems =() => items.Value.AsReadOnly(); 
    } 
    ReadOnlyCollection<string> Items { get { return _getItems(); }} 
} 

そしてこうしてendethたちの愚かなコーディングのトリックを投稿してください。

+3

これは正しい方法だと思います。潜在的に誤用される可能性のあるフィールドの使用を却下するので、 – flq

+6

はい、他の開発者は依然として '_items'に直接アクセスできますが、それは問題ではありません。フィールドは上書きすることはできません( 'readonly'です)。初期化ロジックは' Lazy 'クラスで確実に実行されます。フィールドが複数のスレッドによって同時にアクセスされたとしても、ExpensiveOperationを一度だけ実行する必要がある場合は、コンストラクタに 'LazyThreadSafetyMode.ExecutionAndPublication'を指定することを検討してください。 – porges

+1

私はこのようなことをやっている。実際に何かを読むために、無駄な未来の開発者に頼るのではなく、行の中で起こり得る混乱を避けます。しかし、私は今、この同じ開発者が単に 'ExpensiveOperation'を直接呼び出さないようにするために何が問題になっているのでしょうか。 – spender

12

このような属性を設定すると、探しているものと同じ警告/エラーが生成されることなく、Itemsゲッターはどのようにアクセスしますか?

「他の開発者」とはどういう意味ですか?あなたは(あなたと)、この同じコードに取り組んで別の開発者を意味する場合は、のような簡単なコメント:

///<summary>Do not access directly, using lazy initialization in getter.</summary> 

は、Visual Studioは、いつでも、フィールドの上にマウスを移動することを示しますよう、十分です。

あなたがこのクラスを使用していることを意味するならば、それは情報隠蔽の全体的なポイントであり、あなたは良いことです。

+0

"' Item'ゲッターが同じ警告を出さずにどのようにアクセスするのでしょうか? - '#pragma disable'では、それは素晴らしいことではないと私は同意します。 – Timwi

43

_heyFutureDeveloperDoNotReferenceThisFieldMmmkay

1

_itemsフィールドの名前を変更するには、絶対に何もしません。

よく書き込まれたクラスの公開または保護されたメンバーが、わかりやすい方法でアクセスすることを期待しています。そうでない場合は、十分に文書化する必要があります。

プライベートフィールドでは、私たちがそのような仮定をする理由はありません。

さらに、私がチームの新しい開発者としてこのクラスに来ても、私は_itemsが何をするのか分かりません。私はそれと何をするつもりですか?既存のコードが何をしているかを見るまで、私ができる意味のある仕事はありません。そして、私はそれが怠惰に読み込まれたプロパティのためのバッキングフィールドであることを確認するつもりです。コメントが書かれていても、ちょっとしたことがあればもっともっとそうです。

他のプライベートフィールドで必要なことをランダムに実行し、動作させることは期待できません。

+0

コメントしてもらえませんか? –

-2

どの程度

private Dictionary<String,Object> PandorasCoochie = new Dictionary<String,Object>() 

がそこにあなたのアンタッチャブルプロパティ支持者を置きます。

+2

これはどのように役立ちますか? – svick

+0

これらは動的に宣言されたオブジェクトになり、開発ツールには表示されません。 –

+1

動的言語を使用するだけで静的解析はできません。 –

3

私はこれが非常に有効なものであると思います。残念ながら、C#はこれを念頭に置いて設計されていませんでした。実際には、現在のバージョンの言語ではそれほど実際に行うことはできません。

あなたのチームの開発者を信頼しない場合、あなたはもっと大きな問題を抱えています。

強く反対。あなたが誰かを信頼するならば、、それはでも問題があるときです。最高のコードは誰にも信頼されません。最高のコードは弾丸ではありません。 は誰もが壊すことはありません。

C#はありませんかなり他の多くの言語よりも近づきますが、これを可能にします。

プライベートです。そのお金はそこに止まります。複数の開発者がクラスのプライベートな部分で作業する場合、本当にうまく通信する必要があります。

基本的に同じ引数です。はい、プライベートですが、何ですか?プライベートな情報をうまくカプセル化したいのはなぜそれが有効ではないのですか?

P.S.私は関連した(しかし、直接関係はない)practical approach to enable better bullet-proofing of code in C#を提案しましたが、私は多くの人がそれを見たとは思いません。だからここに行く:)私はプライベートメンバーをカプセル化するための実用的なアプローチを見たいと思う。

6

はい、比較的簡単な方法があります。何人かはハックと考えるかもしれませんが、正当だと思います。今変数itemsはそれを正しく使用する方法にスコープされ

public class Demo 
{ 
    private readonly Func<List<string>> _getItems; 

    public Demo() 
    { 
     List<string> items = null; 
     _getItems =() => 
     { 
      if (items == null) 
       items = ExpensiveOperation(); 
      return items; 
     }; 
    } 

    public List<string> Items { get { return _getItems(); } } 
} 

:それはあなたが望むメソッドレベルのプライバシーを達成するために、ローカル変数のスコープ規則を使用しています。 _getItemsにアクセスすることはまだ可能ですが、それはItemsとまったく同じことをするため、これは重要ではありません。 itemsはローカルであるため、または_getItemsは読み取り専用なので変更できません。

+1

+1反射については、これは良いアイデアであり、私の答えに適用できるリファクタリングを示しています。 –

関連する問題