【问题标题】:Generic grade system通用等级系统
【发布时间】:2014-08-01 18:51:39
【问题描述】:

在我的项目中,我需要一些类似于学生 grade system 的功能,其中必须使用 generics。用户可以输入数据,或者我们可以从数据库中获取数据,但演示基本功能如下所示

 class Student
   {
      private string _name;
      private double _grade;


      public string Name
      {
         get { return _name; }
         set { _name = value; }
      }

      public double Grade
      {
         get { return _grade; }
         set { _grade = value; }
      }


      public Student(string name, double grade)
      {
         this.Name = name;
         this.Grade = grade;
      }
   }



      class Students: List<Student>
       {
          public void Print()
          {
             Console.WriteLine("Student\t\tGrade");
             Console.WriteLine("-------------------------------");
              foreach (Student student in this)
              {
                if (student != null)
                {
                   Console.WriteLine(student.Name + "\t\t" + student.Grade);
                }
             }
          }
       }




     class Program
       {
          static void Main(string[] args)
          {
             Students students = new Students();

         //add the student to the list
         students.Add(new Student("Tom", 83));
         students.Add(new Student("Joe", 86));
         students.Add(new Student("Rudy", 85));
         students.Add(new Student("Chris", 87));
         students.Add(new Student("Keith", 85));
         students.Add(new Student("Pepe", 75));
         students.Add(new Student("Juan", 88.9));
         students.Add(new Student("Pedro", 75));
         students.Add(new Student("Pablo", 75));
         students.Add(new Student("Jose", 79));
         students.Add(new Student("Tommy", 88));

         //implement our custom comparer for grades
         //students.Sort(new StudentGradeComparer());


         students.Print();
         Console.ReadLine();
      }
   }

但后来添加了一些功能,比如我必须打印 A,B,C,F ,而不是像 88 或 76 这样的标记。下面会是这样的,

if (marks >= 80) 
      grade = 'A';
   else if (marks >= 70) 
      grade = 'B';
   else if (marks >= 60)
      grade = 'C';
   else if (marks >= 50)
      grade = 'D';
   else if (marks >= 40)
      grade = 'E';
   else
      grade = 'U'; // unclassified

但在我可枚举和通用的列表中我遇到了困难,请帮助我解决这个问题。使用泛型我的第一段代码工作正常并打印 tom 88 joe 77 等,但我需要 Tom A joe B 和描述的公式第二段代码。所以我在这里的困难是合并这2段代码。谢谢。

【问题讨论】:

  • I am having difficulties 好吧,描述一下困难。不要以为我们知道您的问题是什么。
  • 为什么必须使用泛型?
  • 您没有显示实际返回成绩的代码。请参阅How to create a Minimal, Complete, and Verifiable example
  • @AndrewArnold 不,他没有。他的第二组代码没有在第一组的上下文中显示。问题可能就在那里,但很难说,因为它没有显示出来。
  • 泛型应该如何适应这个?除了通用列表之外,我看不出这里应该是通用的什么

标签: c# oop generics


【解决方案1】:

有不止一种方法可以做到这一点,但我可能会做一些事情,比如在你的 Students 类中添加一个函数 LetterGradeFromNumber(另一种方法是在你的 Student 类中有一个属性,它将返回字母等级):

private string LetterGradeFromNumber(int marks)
{
    if (marks >= 80) 
      return 'A';
    else if (marks >= 70) 
      return 'B';
    else if (marks >= 60)
      return 'C';
    else if (marks >= 50)
      return 'D';
    else if (marks >= 40)
      return 'E';
    else
      return 'U'; // unclassified
    }
}

然后更改Print 以获取参数以在数字和字母等级之间切换(或者您可以根据需要制作单独的函数):

  public void Print(bool letterGrades = false)
  {
     Console.WriteLine("Student\t\tGrade");
     Console.WriteLine("-------------------------------");
     foreach (Student student in this)
     {
        if (student != null)
        {
           Console.WriteLine(student.Name + "\t\t" + letterGrades? LetterGradeFromNumber(student.Grade) : student.Grade.ToString());
        }
      }
  }

【讨论】:

  • +1 为干净的答案(虽然我会做它作为一个属性)
  • @mason:我也倾向于房产,除非需要能够在不同情况下以不同方式映射等级。
  • 根据你的程序去哪里,条件树在它自己的 Grade 类中可能会更好,上面有 toNumber() 和 toLetter() 方法。
  • @jrahhali:不是一个不合理的建议,但我不知道toNumber 会如何工作。如果您通过字母等级,您将无法取回原始数字等级,因为例如,A 超过 80。
  • 使 Grade 成为不可变的值对象: Grade Grade = new Grade(88); grade.toLetter() 返回 'A',grade.toNumber() 返回 88。
【解决方案2】:

首先,我不明白为什么泛型在这里是必须的,或者它们甚至是如何适应的。为什么不能将数字等级添加到字母等级转换方法或属性到您的Student 类?它看起来像:

public class Student
{
    public string LetterGrade {
        get {
            if (Grade >= 80)
                return "A";
            ...
        }
    }
}

或者:

public class Student
{
    public string GetLetterGrade() {
        if (Grade >= 80)
            return "A";
        ...
    }
}

但如果您绝对必须使用通用的某事,您可以执行以下操作:

public class LetterGradeCalculator<T> where T : ILetterGradeFactory, new()
{
    private readonly ILetterGradeFactory _factory;

    public GradeCalculator() {
        _factory = new T();
    }

    public string GetLetterGrade(int numericalGrade) {
        return _factory.CreateLetterGrade(numericalGrade);
    }
}

public interface ILetterGradeFactory
{
    string GetLetterGrade(int numericalGrade);
}

public class SixPointLetterGradeCalculator : ILetterGradeFactory
{
    public string GetLetterGrade(int numericalGrade) {
        if (numericalGrade >= 94)
            return "A";
        ...
    }
}

至少现在LetterGradeCalculator 是通用的...然后用它代替我之前写的LetterGrade 属性。即使我走这条路,我仍然不会使LetterGradeCalculator 通用;我会为构造函数 D.I. 设置它。反而。我真的认为这会使解决方案过于复杂,但至少您可以轻松创建不同的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    相关资源
    最近更新 更多