比较两个对象的最佳方法.测验

本文关键字:最佳 方法 测验 对象 两个 比较 | 更新日期: 2023-09-27 18:35:43

我正在为一些朋友做一个新年前夜测验。测验本身已经完成并正常工作,我只是认为一旦发布答案就自动更正答案会很酷。

问题是将发布的对象与具有所有正确答案的对象进行比较的最佳方法是什么,反射?必须有一种巧妙的方式来做到这一点,并避免有很多如果。

public class QuizModel
{
    public string Name { get; set; }
    public string Quiz1 { get; set; }
    public string Quiz2 { get; set; }
    public string Quiz3 { get; set; }
    etc..
}

你不必给我写任何代码。我只是想要一些关于最好(也是最重要的最酷)方法的指导:)

比较两个对象的最佳方法.测验

至于你的解释,这个类的实现应该是一个答案列表(或字典,或数组等):

public class QuizModel
{
    public string Name { get; set; }
    public List<string> Quizs { get; set; }
}

然后,要检查所有答案是否相同:

public bool AreEqual(model1, model2){
  for(var i = 0; i < Math.Min(model1.Quizs.Count, model2.Quizs.Count); ++i)
    if(model1.Quizs[i] != model2.Quizs[i])
      return false;
  return true;
}

以类似的方式,您可以获得相同的答案数量。

不需要使用反射来比较值,没有:)

如果所有值都封装在一个模型中,那么比较逻辑也应该封装在模型中。 一种简单的方法可能是覆盖.Equals()。 像这样:

public override bool Equals(object obj)
{
    if (obj == null)
        return false;
    if (!(obj is QuizModel))
        return false;
    var quiz = obj as QuizModel;
    return
        quiz.Name.Equals(this.Name) &&
        quiz.Quiz1.Equals(this.Quiz1) &&
        // etc.
}

当然,这是容易的部分。 真正的挑战将是字符串比较逻辑。 字符串听起来像自由文本输入。 因此,如果答案之一是"圣诞节",那么您如何处理"圣诞节"或"圣诞节"或"12 月 25 日"等输入? 这取决于您的业务逻辑。 但是"这两个对象是否相等"的实际逻辑非常简单。

从语义上讲,您可以选择不为此目的覆盖.Equals()。 我可以看到一个很好的论据来反对它,声称对象是不同的,但只是包含相同的值。 (现实世界的一个很好的例子是同卵双胞胎。 因此,您可以选择实现其他内容,例如IEquatable或仅实现自定义方法,例如 .IsEqualTo(QuizModel quiz) . 但无论哪种方式,其中的逻辑都是相同的。

我给你两个问题的解决方案。我想你想给你的朋友打分(我会这样做)。如果是这样,这里有一个解决方案,可以给你答案的分数,我假设每个测验都有相同的值,并且你对所有测验都有正确的答案。首先,您可以尝试通过反射比较测验的所有值,并返回总计(假设您的测验具有相同的值。然后,如果您想在下面更加灵活,我建议您在测验可能具有不同值(分数)时提供可能的解决方案。

1) 公开课测验模型 { 公共字符串名称 { get; set; } 公共字符串 Quiz1 { get; set; } 公共字符串 Quiz2 { get; set; } 公共字符串 Quiz3 { get; set; } }

public class QuizComparer
{
    public QuizComparer(QuizModel correctOne, IComparer<string> comparer, int quizValue = 1)
    {
        this.CorrectOne = correctOne;
        this.Comparer = comparer;
        this.QuizValue = quizValue;
    }
    public int Compare(QuizModel toCompareOne)
    {
        Type type = toCompareOne.GetType();
        var propertiesInfo = type.GetProperties();
        int result = 0;
        foreach (var propertyInfo in propertiesInfo)
        {
            if (propertyInfo.CanRead)
            {
                var toCompareOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(toCompareOne).ToString();
                var correctOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(this.CorrectOne).ToString();
                if (Comparer.Compare(toCompareOnePropertyValue, correctOnePropertyValue) == 0)//equals
                {
                    result += QuizValue;
                }
            }
        }
        return result;
    }
    public QuizModel CorrectOne { get; set; }
    public IComparer<string> Comparer { get; set; }

    public int QuizValue { get; set; }
}

2)其次,如果您想为您的测验提供个人分数,您会发现这非常有帮助:

public class QuizModel
{
    public string Name { get; set; }
    [QuizValue(value: 1)]
    public string Quiz1 { get; set; }
    [QuizValue(value: 2)]
    public string Quiz2 { get; set; }
    [QuizValue(value: 3)]
    public string Quiz3 { get; set; }
}
public class QuizComparer
{
    public QuizComparer(QuizModel correctOne, IComparer<string> comparer, int quizValue = 1)
    {
        this.CorrectOne = correctOne;
        this.Comparer = comparer;
        this.QuizDefaultValue = quizValue;
    }
    public int Compare(QuizModel toCompareOne)
    {
        Type type = toCompareOne.GetType();
        var propertiesInfo = type.GetProperties();
        int result = 0;
        foreach (var propertyInfo in propertiesInfo)
        {
            if (propertyInfo.CanRead && propertyInfo.Name != "Name")
            {
                var toCompareOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(toCompareOne).ToString();
                var correctOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(this.CorrectOne).ToString();
                int value = GetQuizValue(propertyInfo);
                if (Comparer.Compare(toCompareOnePropertyValue, correctOnePropertyValue) == 0)//equals
                {
                    result += value;
                }
            }
        }
        return result;
    }
    private int GetQuizValue(PropertyInfo propertyInfo)
    {
        var attributes = propertyInfo.GetCustomAttributes(typeof(QuizValue), false);
        int value = this.QuizDefaultValue;
        if (attributes != null && attributes.Count() > 0)
        {
            var quizValueAttribute = attributes[0];
            if (quizValueAttribute is QuizValue)
            {
                var quizValue = quizValueAttribute as QuizValue;
                value = quizValue.Value;
            }
        }
        return value;
    }
    public QuizModel CorrectOne { get; set; }
    public IComparer<string> Comparer { get; set; }

    public int QuizDefaultValue { get; set; }
}
[System.AttributeUsage(System.AttributeTargets.Property)]
public class QuizValue : System.Attribute
{
    public QuizValue(int value = 1)
    {
        this.Value = value;
    }
    public int Value
    {
        get;
        set;
    }
}

请尝试如下,愿这将引导您了解您的想法

它将始终将测验 2 与测验 1 值进行比较。

public string Quiz1 {get; set;}
[CompareAttribute("Quiz1", ErrorMessage = "Quiz2 is mismatch with Quiz1")]
public string Quiz2 { get; set; }

只会给你错误的答案:

var quiz = new QuizModel() { Name = "Quiz 1", Quiz1 = "Correct answer", Quiz2 = "Correct answer", Quiz3 = "Correct answer"  };
var correctQuiz = new QuizModel() { Name = "Quiz 1",  Quiz1 = "Correct answer", Quiz2 = "Wrong answer", Quiz3 = "Wrong answer 2" };
Func<QuizModel, List<string>> getListOfAnswers = (currentquiz) => 
(
    from property
    in typeof(QuizModel).GetProperties()
    select property.Name + " " + property.GetValue(currentquiz)
).ToList();
var answers = getListOfAnswers(quiz);
var correctAnswers = getListOfAnswers(correctQuiz); 
var wrongAnswers = correctAnswers.Except(answers);  

输出:

测验2 错误答案

测验3 错误答案2

此解决方案同时使用反射、LINQ 和匿名函数,因此非常酷:)