2012-02-08 103 views
3

是否有可能有一個變量,它是一個類中的實例變量,但只能由特定的屬性來訪問?僅供內部使用的財產私人範圍的變量

我經常創造像這樣的「自我創造」屬性...

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

這意味着我不去重新創建一個新的WGSLocation(或任何對象,我需要的其他類型,這可能是昂貴的創建,或者可能只需要創建一次)每次訪問該屬性。缺點是我的類可以訪問_location變量。但我真的不希望它,所以如果有任何方法有一個實例變量,只能在屬性本身使用?

我想沿着這些線路的東西...

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

我喜歡我的時候測量的渴望創造它是在我的應用程序中的瓶頸使用延遲初始化屬性。 – CodesInChaos 2012-02-08 20:08:52

回答

5

我同意這將是一個很好的語言功能有持續當地人 - 也就是說,變量,其壽命是基於實例的生命週期,但其範圍(區程序文本中按名稱訪問變量是合法的)是本地的。像一些語言一樣,擁有「靜態」本地人也是很好的。

可悲的是,這不是C#中的功能,我們也沒有計劃增加它。很高興有,但很高興有不足以證明費用合理,或推遲或取消「更好有」功能。

這只是「錦上添花」,因爲當然,如果你有一個私人領域,它已經是類的私有實現細節。如果你不想使用它以外的財產做,然後不寫使用它的屬性之外的代碼。如果你的一位同事試圖這麼做,那就把代碼審查放在他們身上吧。

我想我要補充:編寫變異國家財產干將當非常小心。通過默認屬性的getter一邊看着在調試器的目標進行評估,也可以是非常混亂要調試的東西,有調試改變字段的值只是因爲你是檢查對象

+0

關於調試器的好處。我很少使用調試器這些天,所以我忘記了這個問題。 – 2012-02-08 16:35:29

+0

「如果你的同事的一個嘗試這樣做,把在代碼審查嫌下來他們。」我喜歡! – 2012-02-15 10:34:05

+0

對不起,我敢打賭,大多數代碼從來沒有看到代碼審查,並且我個人從不喜歡抨擊我的同事。似乎總是回到我身邊。很想看看你對我的答案的看法。 – AnthonyVO 2013-01-01 19:42:10

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爲一個不錯的解決方案。但還是有點羅嗦!如果在語言中有一種方法可以做到這一點,我寧願這樣做:)除非我在做什麼從根本上來說是錯誤的。 – 2012-02-08 11:55:09

+0

@AntonyScott是的,它是有點羅嗦,但如果你想守護在同一類的其他元素類的元素,我說你應該複查,看看你其實需要兩班。我想你的要求是錯誤的,但我不打擾這些討論。 – 2012-02-08 11:57:33

+0

@AntonyScott其實,只要使用懶惰類。 – 2012-02-08 12:01:58

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

啊,是的。你是對的。我將其更改爲使用空合併運算符。如果它尚未設置,我以前只會創建該對象。好的地方:) – 2012-02-08 20:29:52