C#性质-集合问题

C#性质-集合问题,c#,C#,我在C#工作,我开始玩房地产。我不知道的一件事是,将类属性的集合访问器的逻辑放在什么地方最好,以及如何处理错误 例如,假设我有这个(基本)类: 现在假设我对Age属性有一个要求,0

我在C#工作,我开始玩房地产。我不知道的一件事是,将类属性的集合访问器的逻辑放在什么地方最好,以及如何处理错误

例如,假设我有这个(基本)类:

现在假设我对Age属性有一个要求,0 我应该把它放在酒店里吗

public int Age
    {
        get
        {
            return _Age;
        }
        set
        {
           if (value < 0 || value > 99)
               // handle error
           else
               _Age = Convert.ToInt32(value);
        }
    }
公共信息时代
{
得到
{
回归年龄;
}
设置
{
如果(值<0 | |值>99)
//处理错误
其他的
_年龄=转换为32(值);
}
}
还是通过创建Person对象的类

static void Main(string[] args)
{
   Person him = new Person();
   int NewAge = -10;

   if (NewAge < 0 || NewAge > 100)
      // handle error 
   else
      him.Age = NewAge;
}
static void Main(字符串[]args)
{
人他=新的人();
int NewAge=-10;
如果(新年龄<0 | |新年龄>100)
//处理错误
其他的
他。年龄=新年龄;
}
现在,如果NewAge出现问题(它不符合我的约束条件),该怎么办?我应该创建一个自定义异常并抛出它吗?我是否应该打印一条信息,说明提供有效年龄


我在谷歌上搜索了一下,找不到任何能完全回答我问题的东西。我需要一本书:-/

使用属性设置器,它就是为了这个原因(向字段添加功能)


如果传入了超出范围的值,您可以将其抛出或设置为最小(或最大)值,但这取决于您的流程要求。

将其放入属性中。这是房产的主要用途之一


考虑到你将把责任放在尽可能低的层次上。您给出的示例只需要value参数就可以做出决策。它甚至不依赖于同一类的其他成员。类的其他成员没有理由知道Age属性的有效性是如何工作的,当然也没有理由让任何其他代码知道它。

您将希望将逻辑放入setter中,如果它不符合要求,则抛出异常。但是,您还需要创建一个IsValidAge静态方法或其他方法,以便创建Person的类可以检查年龄值,而不仅仅是查看它是否抛出异常。或者,您可以使用MinAge和MaxAge属性,以便调用代码可以检查它们将要设置的年龄是否介于两者之间


不过,不要创建自定义异常类型,请使用ArgumentOutOfRangeException或类似的方法。

您可能需要查看IDataErrorInfo接口


通过在类中实现此接口,您将向其他机制打开该类,这些机制可以从附加错误信息中获益。

使用setter,并使用ArgumentOutOfRangeException,其他人已经说过


有时,您将调用另一个方法,通常类似于OnAgeChanged(int age),您可以在其中执行验证(这可能是对另一个方法的调用,以便您可以在任何地方使用它)并调用事件处理程序,如果连接到该方法,则可能会应用其他逻辑,具体取决于您使用对象的方式。在您的场景中可能不需要这样做,但对于属性来说,这样做是非常常见的。尤其是当你要更新一个表单时,表单会挂接到AgeChanged事件中进行自我更新。

我将扮演魔鬼代言人的角色,并给出一个答案,说明你为什么不想把它放在setter中。在很多情况下,您希望能够设置年龄属性的值,并在以后询问该对象在整体意义上是否有效

例如,让您的属性保持简单:

public int Age { get; set; }
然后,当传入一个无效值时,您可以使用一些IsValid函数来指示相关对象是否正常。这可能非常有用,因为您可以执行更复杂的验证,而不是简单的年龄限制

bool IsValid()
{
   if (Age < 0 || Age > 99)
     return false;
}

这只是伪代码,但你明白我的意思。这是在setter内部无法实现的,或者至少不能以可维护的方式实现。

我将这样实现它:

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);
}
公共信息时代
{
得到
{
回归年龄;
}
设置
{
if(有效期(值))
_年龄=价值;
其他的
抛出新的ArgumentOutOfRangeException(“value”,string.Format(“value应该介于{0}和{1}之间。”,MinAge,MaxAge));
}
}
私人旅行社有效期(国际)
{

return(age>=MinAge&&age如果您正在进行分解设计(即,在对象的生命周期中,对象的状态在所有点都有效这一点很重要),那么您可能需要在构造函数中设置并检查它。在组件设计中,您需要在使用该属性的方法中检查它,例如

class Person
{
  public int calculateTimeToExpiration()
  {
  if (Age < 0 || Age > 100)
     //throw
  }
}
班级人员
{
public int calculateTimeToExpiration()
{
如果(年龄<0 | |年龄>100)
//扔
}
}

静态void main是客户端代码,不是业务逻辑的好地方。

谢谢您的回答!如果您好奇,我将我的小示例(尽管现在更详细)改为(基于注释)

班级人员
{
私有字符串_FirstName=“Joe”;
私有字符串_LastName=“Smith”;
私家侦探的年龄=18岁;
私有const int MinAge=1;
私有常量int MaxAge=99;
公众人士()
{
}
公众人物(字符串名、字符串名、整数)
{
this.FirstName=FirstName;
this.LastName=LastName;
这个。年龄=年龄;
}
公共字符串名
{
得到
{
返回_FirstName;
}
设置
{
_FirstName=值;
}
}
公共字符串姓氏
{
得到
{
返回_LastName;
}
设置
{
_LastName=值;
}
}
公共信息
{
得到
{
回归年龄;
}
设置
{
if(有效期(值))
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);
}
class Person
{
  public int calculateTimeToExpiration()
  {
  if (Age < 0 || Age > 100)
     //throw
  }
}
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();
    }
 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);
    }