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;
    }
}

そして、新しい学生を作成するとき、実行時のコンパイルエラーや例外のように、グレードを >= 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からダウンロードでき、ドキュメントもそこにあります。Visual Studio の非 Express バージョンとのみ統合され、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 Code Contractsを使用している場合は、これも実行できます。

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 検証ロジックがGrade構造体にあり、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 に答える