5

我想知道是否有办法限制施工中的价值。这是我的代码:

class Student : Human 
{
    private double Grade;

    public Student(string FirstName, string LastName, double Grade)
        : base(FirstName, LastName)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Grade = Grade;
    }
}

当我创建一个新学生时,我想将 Grade 限制在 >= 2.00 和 <= 6.00 之间,例如运行时编译错误或异常。有办法吗?(不用担心其他字段 FirstName 和 LastName)

4

7 回答 7

12

您可以检查它并在运行时抛出异常,如下所示:

if (grade < 2.00 || grade > 6.00)
    throw new ArgumentOutOfRangeException("grade");

始终将此类条件放在方法或构造函数的开头。我什至把它们放在自己的#region(但这是我个人的喜好):

public Student(string firstName, string lastName, double grade)
    : base(firstName, lastName)
{
    #region Contract
    if (grade < 2.00 || grade > 6.00)
        throw new ArgumentOutOfRangeException("grade");
    #endregion
    this.FirstName = firstName;
    this.LastName = lastName;
    this.Grade = grade;
}

但是,有一种方法可以使用 Code Contracts 获得此类事情的编译时警告。您可以在 MSDN 上下载Code Contracts,还可以在那里找到文档。它仅与非 Express 版本的 Visual Studio 集成,由 Microsoft 编写。它将检查方法调用是否可能遵守您指定的合同。您的代码将变为:

using System.Diagnotistics.Contracts;

public Student(string firstName, string lastName, double grade)
    : base(firstName, lastName)
{
    #region Contract
    Contract.Requires<ArgumentOutOfRangeException>(grade >= 2.00);
    Contract.Requires<ArgumentOutOfRangeException>(grade <= 6.00);
    #endregion
    this.FirstName = firstName;
    this.LastName = lastName;
    this.Grade = grade;
}
于 2013-03-15T13:37:30.540 回答
4

您可以抛出异常:

class Student : Human 
{
    private double Grade;

    public Student(string FirstName, string LastName, double Grade)
        : base(FirstName, LastName)
    {
        if (Grade >= 2 && Grade <= 6) { 
          throw new ArgumentOutOfRangeException();
        }

        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Grade = Grade;
    }
}

如果您使用的是Microsoft 代码合同,您也可以这样做:

class Student : Human  {
    private double Grade;

    public Student(string FirstName, string LastName, double Grade)
        : base(FirstName, LastName)
    {
        System.Diagnotistics.Contracts.Contract.Requires<ArgumentOutOfRangeException>(Grade >= 2 && Grade <= 6);

        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Grade = Grade;
    }
}
于 2013-03-15T13:41:01.117 回答
1

还有另一种选择,可能有点繁琐,但会确保给定的范围根本不使用double,而是创建一个名为Grade. 您的Grade课程将包含 from 和 to 的强制转换double,并将强制验证。这意味着所有的 Grade 验证逻辑都在Gradestruct 中,Student类只接收一个Grade对象,不必担心。

public struct Grade
{
    public static readonly double MinValue = 2.0;
    public static readonly double MaxValue = 6.0;

    private double value;

    public static explicit operator double(Grade grade)
    {
        return grade.value + MinValue;
    }

    public static explicit operator Grade(double gradeValue)
    {
        if (gradeValue < MinValue || gradeValue > MaxValue)
            throw new ArgumentOutOfRangeException("gradeValue", "Grade must be between 2.0 and 6.0");

        return new Grade{ value = gradeValue - MinValue };
    }
}

你会像这样使用它:

double userInput = GetUserInputForGrade();
Grade grade = (Grade)userInput; // perform explicit cast.
Student student = new Student(firstName, lastName, grade);

编辑:我已经使用@EricLippert 的建议更新了代码,以使该类向开发人员公开其最小/最大值。

编辑 2:再次更新 @JeppeStigNielsen 的建议。该value字段现在存储 MinValue 的偏移量,因此无论 0 是否在有效范围内,调用都default(Grade)将返回一个有效值(等于 MinValue)。

于 2013-03-15T13:48:47.007 回答
0
class Student : Human 
{
    private double Grade;

    public Student(string FirstName, string LastName, double Grade)
        : base(FirstName, LastName)
    {
        if (Grade < 2 || Grade > 6)
            throw new ArgumentOutOfRangeException("Grade must be between 2 and 6");

        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Grade = Grade;
    }
}
于 2013-03-15T13:39:24.053 回答
0
public Student(string FirstName, string LastName, double Grade)
    : base(FirstName, LastName)
    {
     if(Grade >= 2.0 || Grade <= 6.00)
      throw  new ArgumentException("your message");     
    }
于 2013-03-15T13:39:26.987 回答
0

如果您想要任何编译时间检查的机会,您必须使用代码合同。它们本质上是运行时的异常,因此相当于带有异常的参数验证。

public Student(string firstName, string lastName, decimal grade)
{
    Contract.Requires(grade >= 2);
    Contract.Requires(grade <= 6);

    FirstName = firstName;
    LastName = lastName;
    Grade = grade;     
}

看到这个问题

由合同和施工人员设计

于 2013-03-15T13:42:00.847 回答
-2
class Student : Human 
{
    private double Grade;

    public Student(string FirstName, string LastName, double Grade)
        : base(FirstName, LastName)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
        this.Grade = Grade;
        if(Grade >= 2 and Grade <= 6){
            throw new Exception("Incorrect grade input");
    }
}

或者抛出你想要的相关异常,例如 ArgumentOutOfException 等......

于 2013-03-15T13:37:34.053 回答