Microsoft已将其作为框架设计指南,properties应该彼此独立,而不是依赖于按任何特定顺序设置。
假设您有一个需要支持dimmensions和面积计算的三角形类。你会如何模仿这个?
这当然是被认为是gauche的设计,因为Area依赖于Base和Height首先设置:
class Triangle{
public double Base {get;set;}
public double Height {get;set;}
public double Area {
get{
return (Base * Height) / 2;
}
}
}
假设您使用构造函数,您可以确保此案例的默认值,但这是正确的方法吗?
class Triangle{
public Triangle(double b, double h){
Base = b;
Height = h;
}
public double Base {get;set;}
public double Height {get;set;}
public double Area {
get{
return (Base * Height) / 2;
}
}
}
您仍然拥有一个依赖于其他属性的属性。为了成为一个纯粹主义者,我只能看到几种方法(我想它们可以结合起来):
Make Base / Height具有只能在构造函数中设置的只读成员
将面积计算成方法。
使用某种工厂模式+ readonly成员来确保尽管可能存在依赖关系,但只能通过实例化Triangle类的方法来设置值。
问题:
指南是否切实可行(为了支持它,您是否必须在类中建立很多复杂性)? [例如,SqlConnection类允许您初始化连接字符串属性,但允许您更改它的各个部分,例如命令超时]
如何管理保持您的财产彼此独立?
对于使用Silverlight / MVVM类型体系结构的人来说,由于数据绑定对象的工作方式,您是否接受属性中的依赖项?例如,绑定一个在屏幕上显示高度,基数和面积的三角形实例。
答案 0 :(得分:15)
微软真的试图说“不要以这样一种方式设计你的类,即以任意顺序调用属性会导致意外行为。”您班级的用户不希望请求值(使用属性)产生尴尬的副作用。
这属于最不意外的原则。
我认为这是一个完全实用的指南。属性不应该有意想不到的副作用。
你提出了一个很好的问题:“你如何管理保持你的财产彼此独立?”。非常小心!我尽可能地消除状态(并相应地减少属性的数量)。此外,通过分解类来分区状态是另一种策略。这本身就是一个很好的问题......
就三角形类而言,我认为您在代码中呈现的两种解决方案都是有效的。如果由我决定,我会设计三角形以使其不可变,并在构造函数中获取宽度和高度。
答案 1 :(得分:3)
最简单的方法是仅在构造函数上接受base和height值,然后将它们作为只读属性公开:
class Triangle
{
private double base;
private double height;
private Triangle() { }
public Triangle(double base, double height)
{
this.base = base;
this.height = height;
}
public double Base
{
get
{
return this.base;
}
}
public double Height
{
get
{
return this.height;
}
}
public double Area
{
get
{
return (this.base * this.height) / 2;
}
}
}
答案 2 :(得分:2)
我想我会选择一个Triangle类,它有一个构造函数,它带有Base&高度作为参数,因为三角形不能存在(imho)没有基础或高度。
Offcourse,Area属性依赖于Base&身高,但我觉得这没问题? 我认为MS指南应解释如下:
属性应该独立于 彼此而不依赖于存在 按任何特定顺序设置。
含义-imho-您不应该首先必须设置Base属性,并且只有在设置了Base属性后才能设置Height属性。 我认为这就是上述指南的意思。
接下来,您的Area属性不可设置,因此没有问题。 :)
答案 3 :(得分:0)
某些属性本质上是相关的和相关的。关键是首先设置基础,然后高度应该与设置高度相同,然后是基础。没有设置其中一个,那么检查该区域是没有意义的。
答案 4 :(得分:0)
选择选项2.将区域设为方法并将其命名为CalculateArea。属性应该用于封装状态而不是行为。该区域可以从基数和高度计算并不意味着它本身应该是状态;相反,这是一个强有力的论据,即Area应该不成为州。
class Triangle
{
public Triangle(double b, double h)
{
Base = b;
Height = h;
}
public double Base { get; set; }
public double Height { get; set; }
public double CalculateArea()
{
return (Base * Height) / 2;
}
}
这让消费者知道,获取三角形区域需要真正的工作,而不是简单地访问状态。