我在C#工作,我开始玩房产了。我不知道的一件事是什么是为类属性的set访问器设置逻辑以及如何处理错误的最佳方式/位置。
例如,假设我有这个(基础)课程:
class Person
{
private int _Age = 18;
public Person()
{
}
public int Age
{
get
{
return _Age;
}
set
{
_Age = value;
}
}
}
现在说我对Age属性有一个要求,0&lt;年龄< 100.我在哪里列出这个逻辑?
我应该把它放在房产里吗?
public int Age
{
get
{
return _Age;
}
set
{
if (value < 0 || value > 99)
// handle error
else
_Age = Convert.ToInt32(value);
}
}
或通过创建Person对象的类?
static void Main(string[] args)
{
Person him = new Person();
int NewAge = -10;
if (NewAge < 0 || NewAge > 100)
// handle error
else
him.Age = NewAge;
}
现在如果NewAge出现问题(它不符合我的约束条件)怎么办?我应该创建一个自定义异常并抛出它吗?我应该打印一条消息说是否提供有效年龄?
我做了一些谷歌搜索,我找不到任何能完全回答我问题的内容。我需要一本书: - /
答案 0 :(得分:23)
使用属性设置器,就是出于这个原因(向字段添加功能)。
如果传入超出范围的值,您可以抛出ArgumentOutOfRangeException或仅将其设置为最小(或最大)值,但这取决于您的流程要求。
答案 1 :(得分:11)
我会像这样实现它:
public int Age
{
get
{
return _Age;
}
set
{
if (IsValidAge(value))
_Age = value;
else
throw new ArgumentOutOfRangeException("value", string.Format("value should be between {0} and {1} inclusive.", MinAge, MaxAge));
}
}
private bool IsValidAge(int age)
{
return (age >= MinAge && age <= MaxAge);
}
有几点需要注意:
答案 2 :(得分:6)
如果不符合要求,您将需要将逻辑放入setter并抛出异常。但是,您还需要创建一个IsValidAge静态方法,以便创建Person的类可以检查年龄值,而不仅仅是看它是否抛出异常。或者,您可以使用MinAge和MaxAge属性,因此调用代码可以检查它们即将设置的年龄是否介于它之间。
不要创建自定义异常类型,使用ArgumentOutOfRangeException或类似的东西。
答案 3 :(得分:3)
把它放在财产中。这是物业的主要目的之一!
考虑到您将责任放在最低级别。您提供的示例不需要 value 参数以外的任何内容来做出决定。它甚至不依赖于同一类的其他成员。没有理由让班上的其他人知道Age属性的有效性如何,当然也没有理由让任何其他代码知道它。
答案 4 :(得分:3)
您可能需要查看IDataErrorInfo接口。
通过在类中实现此接口,您可以将该类打开到可以从其他错误信息中受益的其他机制。
答案 5 :(得分:1)
我将扮演魔鬼的拥护者并给出答案,为什么你不想把它放在制定者中。有很多情况下,您希望能够设置Age属性的值,并在以后询问该对象在整体意义上是否有效。
例如,保持您的财产简单:
public int Age { get; set; }
然后,当传入无效值时,您可以使用一些IsValid函数来指示相关对象是否正常。这非常有用,因为除了简单的年龄限制之外,您可以进行更复杂的验证。
bool IsValid()
{
if (Age < 0 || Age > 99)
return false;
}
对于像这样简单的东西没有太多好处,但也要考虑你可以在持久层中使用它,这样你就可以确保任何无效的对象永远不会被持久化。在这些情况下,您不一定要抛出异常。
还要考虑这个:
DateTime StartDate { get; set; }
DateTime EndDate { get; set;}
bool IsValid()
{
return StartDate > EndDate
}
这只是伪代码,但你明白我的观点。这是你在setter中无法做到的事情,或者至少是不可维护的。
答案 6 :(得分:0)
使用setter,并使用ArgumentOutOfRangeException,正如其他人已经说过的那样。
有时你会调用另一个方法,通常是OnAgeChanged(int age),你可以在那里执行验证(可能是对另一个方法的调用,所以你可以在任何地方使用它)并调用一个事件处理程序,如果连接,可能有其他逻辑应用取决于您如何使用您的对象。在您的方案中可能没有必要,但对于属性来说这是很常见的。特别是如果您要更新表单 - 表单将挂钩到AgeChanged事件以进行更新。
答案 7 :(得分:0)
如果您正在进行因式设计(即,对象的状态在对象生命期内的所有点都有效),那么您可能需要在构造函数中设置并检查它。在组件设计中,您需要在使用该属性的方法中进行检查,例如
class Person
{
public int calculateTimeToExpiration()
{
if (Age < 0 || Age > 100)
//throw
}
}
静态void main是客户端代码,不是业务逻辑的好地方。
答案 8 :(得分:0)
感谢您的回答!如果你好奇这里是我改变我的小例子(尽管现在更详细)到(基于评论)。
class Person
{
private string _FirstName = "Joe";
private string _LastName = "Smith";
private int _Age = 18;
private const int MinAge = 1;
private const int MaxAge = 99;
public Person()
{
}
public Person(string FirstName, string LastName, int Age)
{
this.FirstName = FirstName;
this.LastName = LastName;
this.Age = Age;
}
public string FirstName
{
get
{
return _FirstName;
}
set
{
_FirstName = value;
}
}
public string LastName
{
get
{
return _LastName;
}
set
{
_LastName = value;
}
}
public int Age
{
get
{
return _Age;
}
set
{
if (IsValidAge(value))
throw new ArgumentOutOfRangeException("value","Please enter a positive age less than 100.");
else
_Age = value;
}
}
private bool IsValidAge(int age)
{
return (age < MinAge || age > MaxAge);
}
public override string ToString()
{
if (Age == 1)
return "My name is " + FirstName + " " + LastName + " and I am " + Age + " year old.";
else
return "My name is " + FirstName + " " + LastName + " and I am " + Age + " years old.";
}
}
static void Main(string[] args)
{
Person him, her;
try
{
him = new Person("Joe Bob", "McGruff", 1);
Console.WriteLine(him);
}
catch (ArgumentOutOfRangeException range)
{
Console.WriteLine(range.Message);
}
try
{
her = new Person();
her.Age = -5;
Console.WriteLine(her);
}
catch (ArgumentOutOfRangeException range)
{
Console.Write(range.Message);
}
Console.ReadKey();
}
答案 9 :(得分:0)
您的更新答案很好,但您应该在您的setter / validation中清理一小段
public int Age
{
get
{
return _Age;
}
set
{
if (!IsValidAge(value))
throw new ArgumentOutOfRangeException("Age","Please enter a positive age less than 100.");
_Age = value;
}
}
private bool IsValidAge(int age)
{
return (age > MinAge && age < MaxAge);
}