C# 匿名函数或数千个类的列表

C# 匿名函数或数千个类的列表,c#,function,anonymous,C#,Function,Anonymous,我希望创建一个在线测验,可以从数千个编程问题中提出任何问题。每个问题都是通过一个函数创建的,该函数给出一个int数组,其值决定所显示的确切问题。我每堂课都有一个问题: public class AddingTwoDigitNumbers : IQuestion { public string QName() { return "Adding Two-Digit Numbers" }; public int[] QParams() { return int[]() {Random(

我希望创建一个在线测验,可以从数千个编程问题中提出任何问题。每个问题都是通过一个函数创建的,该函数给出一个int数组,其值决定所显示的确切问题。我每堂课都有一个问题:

public class AddingTwoDigitNumbers : IQuestion
{
    public string QName() { return "Adding Two-Digit Numbers" };
    public int[] QParams() { return int[]() {Random(10, 99), Random(10, 99) };
    public void Question(int[] values) {
        Console.WriteLine(string.Format("What is {1} + {2}?", values[0], values[1]);
    }
    public void Answer(int[] values) {
        Console.WriteLine(values[0] + values[1]).ToString());
    }
}
QParams
创建int数组(精确确定所创建的问题),该数组被赋予
question
Answer
以创建问题和答案

我想要一个可通过
QName
搜索的
问题列表
,但我不想创建(并命名)数千个实现
IQuestion
的类

这是我的第二个解决方案:

public class Question
{
    public string QName { get; set; }
    public Func<int[]> QParams { get; set; }
    public Action<int[]> Question { get; set; }
    public Action<int[]> Answer { get; set; }
}

public class QuestionRepository
{
    public static Dictionary<string, Question> Questions = new Dictionary<string, Question>();
    public static void AddQuestions(Question[] qs) {
        foreach (Question q in qs) Questions.Add(q.QName, q);
    }
}

public class FirstSetOfQuestions
{
    static void AddQuestions()
    {
        QuestionRepository.AddQuestions(new Question[]
        {
            new Question()
            {
                QName = "Adding Two-Digit Numbers",
                QParams = () => int[]() {Random(10, 99), Random(10, 99) },
                Question = (v) => {Console.WriteLine(string.Format("What is {1} + {2}?", v[0], v[1]);},
                Answer = (v) => {Console.WriteLine(values[0] + values[1]).ToString());}
            },
            new Question()
            {
                QName = "Subtracting Three-Digit Numbers",
                QParams = () => int[]() {Random(100, 999), Random(100, 999) },
                Question = (v) => {Console.WriteLine(string.Format("What is {1} - {2}?", v[0], v[1]);},
                Answer = (v) => {Console.WriteLine(values[0] - values[1]).ToString());}
            }
        }
    }
}
公开课问题
{
公共字符串QName{get;set;}
公共Func QParams{get;set;}
公共行动问题{get;set;}
公共操作答案{get;set;}
}
公共类问题库
{
公共静态字典问题=新建字典();
公共问题(问题[]qs){
foreach(qs中的问题q)问题。添加(q.QName,q);
}
}
公共类第一组问题
{
静态void AddQuestions()
{
QuestionRepository.AddQuestions(新问题[])
{
新问题(
{
QName=“添加两位数”,
QParams=()=>int[](){Random(10,99),Random(10,99)},
问题=(v)=>{Console.WriteLine(string.Format(“什么是{1}+{2}?”,v[0],v[1]);},
答案=(v)=>{Console.WriteLine(值[0]+值[1]).ToString();}
},
新问题(
{
QName=“减去三位数”,
QParams=()=>int[](){Random(100999),Random(100999)},
问题=(v)=>{Console.WriteLine(string.Format(“什么是{1}-{2}?”,v[0],v[1]);},
答案=(v)=>{Console.WriteLine(值[0]-值[1]).ToString();}
}
}
}
}
所以我的问题是哪一个更好?我是创建数千个类,必须为每个类提供名称,还是创建数千个匿名函数和一个使用(我假设)委托存储这些的类?如果我有数千个问题,第二个解决方案是否有问题,或者甚至有更好的方法


(很明显,我想提出的问题比这里显示的要复杂得多,涉及分数、代数等。)

两种方法都是错误的。我想你不会有成千上万种不同类型的计算。你只会有十几种或几十种不同类型的计算,对各种各样的数据进行操作

因此,您需要规范化您的数据,以便在定义良好的数据数据库上完成十几个或几十个不同的定义良好的计算,然后编写十几个或几十个类,每种计算一个


您可能会认为这太复杂了,您可能会认为编写数千个类(或委托,其实并不重要)可能需要做很多工作,但每一部分都很小,很简单,但是相信我,当接口或所有这些类的实现需要更改时,您会非常后悔这样做,而且大多数情况下,在某个时间点需要更改某些内容。

只是为了让您从流畅的语法开始,通过在那里加入一些存根和想法

class Question
{
    public string Name { get; set; }
    public string QuestionFormat { get; set; }
    public List<Range> Args { get; set; }
    public Expression<Func<int[], int>>  ValExp { get; set; }

    public Question(string name, string questionFormat)
    {
        this.Name = name;
        this.QuestionFormat = questionFormat;
        this.Args = new List<Range>();
    }

    public Question Rand(int min, int max)
    {
        this.Args.Add(new Range(min, max));
        return this;
    }

    public void Val(Expression<Func<int[], int>> exp)
    {
        this.ValExp = exp;
    }

    public CompiledQuestion Compile()
    {
        // Generate args in the appropriate ranges
        // Evaluate the result with the ValExp
        // Return a new CompiledQuestion with the information -
        //    basically just replacing Args, ValExp with RealArgs, Val
    }

    public ICoolDataObject Save()
    {
    }

    public static Question Load(ICoolDataObject hmm)
    {
    }
}

class Range
{
    public int Min { get; set; }
    public int Max { get; set; }

    public Range(int min, int max)
    {
        this.Min = min;
        this.Max = max;
    }
}

显然,您可以添加一些验证检查,以避免由于工作时间太晚而导致的错误参数数量,并使用
double
decimal
而不是
int

为什么不将问题数据存储在DB中?您可以存储表达式,甚至可以存储C代码并动态编译。我不熟悉数据库ny很好的表达式序列化库,但是存储代码非常简单。您可以直接存储代码的文本(例如
“x+y=Math.PI”
)。要在以后编译它,请使用
CSharpCodeProvider
,根据需要添加所需的名称空间和变量声明。@CapIsland:如果是这样,我认为更好的方法是
IQuestion
实现,由应用程序的某个区域捆绑到程序集中(例如,“三角问题”)。在运行时将它们作为插件加载,当您需要添加另一个问题时,保持测验“core”不变。使用C#code+某种管理工具的DB对您没有帮助,因为这样您就需要好的代码和/或表达式编辑器(而现在您已经有了它-Visual Studio)。@CapIsland“Skeet”这是Skeet先生!我在课堂上有很多计算。我为点、直线、分数、方程等创建了课堂。这大大减少了
问题
答案
的功能。非常感谢。这真的很酷,可能会很有用。
new Question("simple addition",
             "whats {0} + {1}?")
    .Rand(10, 99)
    .Rand(10, 99)
    .Val(v => v[0] + v[1]);