物业实施 - Noob缺乏知识
我相信这已被回答之前抱歉,但我不能凝结我的问题,以一个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;
}
}
干杯....
我认为你有两个选择:
-
确保的
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; } }
-
有两个类:
Pt3Mutable
和Pt3Immutable
(或一些更好的名字)。Pt3Immutable
将是不可变的,所以你可以安全地使用它Normal
。Pt3Mutable
将是可变的,所以如果你用它Location
,方法1,仍能正常工作。然后,您可以将演员操作员在两种类型之间进行转换:隐式投射从
Pt3Mutable
到Pt3Immutable
,并显式转换。
如果PT3是你的类,去掉制定者,(X,Y ,Z)或者将它们私人化。
假设Normal
和Location
必须是相同的类型,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;
}
}
Pt3
也许应该是一个结构,并作为不可变值处理。
取下制定者,只允许通过构造函数坐标的设定。那么你的类型的用户将不能够在同一时间改变一个属性当的Normal
值已改变RegionProvider
将永远知道。
这是非常如何System.Drawing.Point的行为,除了Point
允许X和Y是造成各种问题,使人们在试图像
Foo.Bar.X += 10;
,而不是
Foo.Bar += new Size(10, 0);
为什么它应该是'struct'? – svick 2012-07-22 23:44:20
我认为它应该是一个结构,因为我希望表示一个点的类型像一个值一样,是不可变的,并通过复制传递。我可能受BCL定义点和相关类型为结构的影响。 – 2012-07-23 01:21:07
我会的东西说问题在于你对'好东西'的陈述。
如果你决定,你想有一个载体类(您PT3),使用它作为这样。定义'Normalize()'方法并明确使用它。
嗯,这是我的意见,无论如何。
标准.NET陷阱,从来没有以同样的方式,总是同样的问题。 Normal属性是一个值类型,当您访问它时会得到一个副本。您将更新副本,而不是原件。样板的智慧是“不要改变结构”。 – 2012-07-22 22:47:59
@HansPassant我不认为这个问题是关于struct的。这是关于不允许独立设置属性的属性。 – svick 2012-07-22 23:42:12