2012-07-22 58 views
2

我相信這已被回答之前抱歉,但我不能凝結我的問題,以一個googlable短語。物業實施 - Noob缺乏知識

我有一個Pt3類,這是一個3D笛卡爾點(x,y,z屬性加上一些其他的好東西)。我使用Pt3類型作爲RegionProvider類中的get/set屬性值 - Location和Normal。

的位置屬性是好的,我不在乎財產是如何設置的:

//Location set method 1 - sweet... 
RegionProvider Foo = new RegionProvider(); 
Foo.Location.x = 10; 
Foo.Location.y = 20; 
Foo.Location.z = 30; 

//Location set method 2 - also sweet... 
RegionProvider Foo2 = new RegionProvider(); 
Foo2.Location = new Pt3(10, 20, 30); 

的普通屬性,雖然需要不同的行爲。如果需要,我希望RegionProvider類將輸入標準化爲Normal屬性。如果調用者將「正常」值設置爲40,50,60,則RegionProvider類將歸一化爲0.4558,0.5698,0.66838(給出向量長度== 1)。如果主叫方將執行以下操作,一切都很酷...

//Normal set method A - sweet... 
Foo.Normal = new Pt3(40, 50, 60); 

...但如果如果他們做到這一點悲傷將接踵而至:

//Normal set method B - grief... 
Foo2.Normal.x = 40; 
Foo2.Normal.y = 50; 
Foo2.Normal.z = 60; 

...因爲RegionProvider類將作爲正常化每個元素都被設置。我想要做的是防止調用者看到Normal屬性的x,y,z,所以他們被迫使用上面的方法'A'。

一個解決方案可能是不規範化屬性設置,但規範化屬性獲取但這看起來像fakery。

對於它的價值,這是我的普通財產申報:提前任何幫助

/// <summary> 
/// Property for the objects normal 
/// </summary> 
public Pt3 Normal 
{ 
    set 
    { 
     _normal = Bit555ModelCore.NormalizeVector(value); 
     this.NotifyPropertyChanged("Normal"); 
    } 
    get 
    { 
     return _normal; 
    } 
} 

乾杯....

+0

標準.NET陷阱,從來沒有以同樣的方式,總是同樣的問題。 Normal屬性是一個值類型,當您訪問它時會得到一個副本。您將更新副本,而不是原件。樣板的智慧是「不要改變結構」。 – 2012-07-22 22:47:59

+0

@HansPassant我不認爲這個問題是關於struct的。這是關於不允許獨立設置屬性的屬性。 – svick 2012-07-22 23:42:12

回答

0

我認爲你有兩個選擇:

  1. 確保的Pt3性能決不會被使整個班級不變的獨立設置:

    class Pt3 
    { 
        public Pt3(double x, double y, double z) 
        { 
         X = x; 
         Y = y; 
         Z = z; 
        } 
    
        public double X { get; private set; } 
        public double Y { get; private set; } 
        public double Z { get; private set; } 
    } 
    
  2. 有兩個類:Pt3MutablePt3Immutable(或一些更好的名字)。 Pt3Immutable將是不可變的,所以你可以安全地使用它NormalPt3Mutable將是可變的,所以如果你用它Location,方法1,仍能正常工作。

    然後,您可以將演員操作員在兩種類型之間進行轉換:隱式投射從Pt3MutablePt3Immutable,並顯式轉換。

0

如果PT3是你的類,去掉制定者,(X,Y ,Z)或者將它們私人化。

0

假設NormalLocation必須是相同的類型,PT3可以有簡單的屬性:

public bool CanSetXyz { get; } 

對於Location,此屬性初始化到true。對於Normal,請將其初始化爲false

然後在每個X,Y和Z屬性:

private int _x; 

public int X 
{ 
    get { return _x; } 
    set 
    { 
     if (!CanSetXyz) 
     { 
      throw new CantSetXyzException("Can't set X on a Normal point."); 
     } 
     _x = value; 
    } 
} 

如果他們不必是同一類型,你想使一個共同的基類與總是分享的內容之間,然後一個班級不會有X,Y和Z的安裝人員,另一個班級會有公共安裝人員。

實施例:

public abstract class BasePt3 
{ 
    protected int x; 
} 

public class LocationPt3 : BasePt3 
{ 
    public int X 
    { 
     get { return x; } 
     set { x = value; } 
    } 

    public LocationPt3(int _x) 
    { 
     x = _x; 
    } 
} 

public class NormalPt3 : BasePt3 
{ 
    public int X 
    { 
     get { return x; } 
    } 

    public NormalPt3(int _x) 
    { 
     x = _x; 
    } 
} 

編輯:甲或許更有用的例子,與所述基類允許X被讀取:

public abstract class BasePt3 
{ 
    protected int x; 

    public int X 
    { 
     get { return x; } 
    } 
} 

public class LocationPt3 : BasePt3 
{ 
    public new int X 
    { 
     get { return x; } 
     set { x = value; } 
    } 

    public LocationPt3(int _x) 
    { 
     x = _x; 
    } 
} 

public class NormalPt3 : BasePt3 
{ 
    public new int X 
    { 
     get { return x; } 
    } 

    public NormalPt3(int _x) 
    { 
     x = _x; 
    } 
} 
0

Pt3也許應該是一個結構,並作爲不可變值處理。

取下制定者,只允許通過構造函數座標的設定。那麼你的類型的用戶將不能夠在同一時間改變一個屬性當的Normal值已改變RegionProvider將永遠知道。

這是非常如何System.Drawing.Point的行爲,除了Point允許X和Y是造成各種問題,使人們在試圖像

Foo.Bar.X += 10; 

,而不是

Foo.Bar += new Size(10, 0); 
+0

爲什麼它應該是'struct'? – svick 2012-07-22 23:44:20

+0

我認爲它應該是一個結構,因爲我希望表示一個點的類型像一個值一樣,是不可變的,並通過複製傳遞。我可能受BCL定義點和相關類型爲結構的影響。 – 2012-07-23 01:21:07

0

我會的東西說問題在於你對'好東西'的陳述。

如果你決定,你想有一個載體類(您PT3),使用它作爲這樣。定義'Normalize()'方法並明確使用它。

嗯,這是我的意見,無論如何。