2012-02-08 11 views
3

クラス内のインスタンス変数ですが、特定のプロパティによってのみアクセスできる変数を持つことは可能ですか?プロパティ内での使用のために限定スコープの変数

私はかなり頻繁にそのような「自己作成」プロパティを作成して...私は新しいWGSLocation(またはその他何でも、私は必要なオブジェクトの種類を再作成に行かないことを意味し

private IWGSLocation _location; 
public IWGSLocation Location 
{ 
    get 
    { 
     _location = _location ?? new WGSLocation(); 
     _location.Latitude = Latitude.GetValueOrDefault(0); 
     _location.Longitude = Longitude.GetValueOrDefault(0); 
     return _location; 
    } 
} 

、作成には高価な場合があります)、またはプロパティにアクセスするたびに1回のみ作成する必要があります。欠点は、私のクラスが_location変数にアクセスできることです。しかし、私は本当にそれを望んでいないので、プロパティ自体の中でのみ使用できるインスタンス変数を持つ方法があれば?私はこれらの線に沿って何かを考えている

...

public IWGSLocation Location 
{ 
    get 
    { 
     WGSLocation _location = _location ?? new WGSLocation(); 
     _location.Latitude = Latitude.GetValueOrDefault(0); 
     _location.Longitude = Longitude.GetValueOrDefault(0); 
     return _location; 
    } 
} 
+1

私はアプリケーションのボトルネックであることを熱心に評価したときに、遅延初期化プロパティを使用することをお勧めします。 – CodesInChaos

答えて

5

からつまり、その寿命のインスタンスの有効期間に基づいていますがスコープの変数を(地方変数に名前でアクセスすることが合理的なプログラムテキスト)はローカルです。いくつかの言語がそうであるように、 "静的な"ローカルを持つこともいいでしょう。

悲しいことに、これはC#の機能ではなく、追加する予定はありません。それは良いことですが、持っていればいいのは、費用を正当化するのに十分ではなく、「持っている方がいい」という機能を延期したり取り消したりするのに十分ではありません。

プライベートフィールドを持っている場合はもちろん、それはクラスのプライベートな実装の詳細です。プロパティ外で使用しない場合はの外で使用するコードは書きません。あなたの同僚の1人がそうしようとするなら、コードレビューで彼のことをやめてください。

私は、追加するかもしれないと思った:状態を突然変異させるプロパティゲッターを書くときは非常に注意してください。デバッガでオブジェクトを見ながら、デフォルトのプロパティのゲッターによってが評価され、それが何かをデバッグする非常に混乱こと、あなたがオブジェクトを調べるあるという理由だけでデバッガは、フィールドの値を変更することができます。

+0

デバッガに関する良い点。私はまれにデバッガを使用することはほとんどないので、そのことについて忘れてしまいました。 –

+0

"あなたの同僚の一人がそうしようとすると、コードレビューでスムージングを入れてください。"私はそれが好きです! –

+0

申し訳ありませんが、ほとんどのコードではコードレビューを見ることはできず、個人的には私の同僚に叩かれたことは決してありませんでした。いつも私に戻ってくるようです。あなたが私の答えをどう思っているのか知りたい。 – AnthonyVO

1

クラスがアクセスできるという事実は必ずしも欠点ではありません。同じエンティティにはまだ論理的にカプセル化されています。

の後に何をしているのですか?は、あなたが望む方法ではありません。メンバー変数はクラスのすべての領域で表示され、ローカル変数は定義されたスコープに制限されています。

代わりに、場所をコンテナクラス内にラップすることができます。このクラスはメンバ変数です。返すときIWGSLocationあなたは単にコンテナクラスにドリル:

public class LocationContainer 
{ 
    public IWGSLocation InnerLocation { get; private set; } 

    public void SetLocation(WGSLocation loc) 
    { 
     InnerLocation = loc; 
    } 
} 

private readonly LocationContainer _container = new LocationContainer(); 

public IWGSLocation Location 
{ 
    get 
    { 
     if (_container.InnerLocation == null) 
     { 
      _container.SetLocation(...); 
     } 

     return _container.InnerLocation; 
    } 
} 

これは_containerに触れてからクラスを止めるつもりはないが、それは彼らが行う前に、他の開発者が二度考えるようになりますと、彼らは偶然にできなくなります明示的にSetLocationを呼び出さずに場所を変更してください。

コンテナのSetLocationに一度ガードすることもできます。

アップデート:私は実際のようなもの、ここで怠惰なクラスを使用したい:

private readonly Lazy<IWGSLocation> _location = new Lazy<IWGSLocation>(() 
=> 
{ 
    var l = new WGSLocation(); 
    l.Latitude = Latitude.GetValueOrDefault(0); 
    l.Longitude = Longitude.GetValueOrDefault(0); 
    return l; 
}); 

public IWGSLocation Location 
{ 
    get { return _location.Value; } 
} 

が警告され、これは、ヘッドコンパイルされました! :-)私はそれが永続的な地元の人々持っている素敵な言語機能になり同意

+0

+1素晴らしいソリューションです。しかしまだ少しばかげている!もし私がやっていることが何らかの形で根本的に間違っていない限り、これを行うための言語の方法があれば、私はそれを好むでしょう。 –

+0

@AntonyScottはい、それは少し言葉ですが、同じクラスの他の要素からクラスの要素を保護しようとしている場合は、実際に2つのクラスが必要かどうかを確認する必要があります。あなたの要件が間違っているという議論があると思いますが、私はそれらの議論を気にしません。 –

+0

@AntonyScott実際、レイジークラスを使用するだけです。 –

1

あなたの現在の実装は私に壊れています。

var x=obj.Location; 
x.Latitude = 1; 
Console.WriteLine(x.Latitude);//1 
var y=obj.Location; 
Console.WriteLine(x.Latitude);//WTF it changed 

私はIWGSLocationは不変作る、または作成のみで、それを修正し、あなたが望むどのセマンティクスに応じてお勧めします。

+0

ああ、はい。あなたが正しい。私はヌル合体演算子を使用するように変更しました。私は、オブジェクトがまだ設定されていない場合にのみ作成していました。良い点:) –

関連する問題