I've programmed a few Project Euler problem but they are all separated in different solutions so I decided to group them all together in a nice Windows forms application. Here's how it looks like : You can select any of the available problems from the list check the answer and the execution time. I'm looking primarly for code style review or maybe a better way of separating classes and the overall architecture.Main form classpublic partial class Form1 : Form{    private readonly Dictionary<string, IProblem> problems = new Dictionary<string, IProblem>();    private readonly Dictionary<int, ProblemOutput> solvedProblems = new Dictionary<int, ProblemOutput>();    private IProblem currentProblem;    public Form1()    {        InitializeComponent();        LoadProblems();    }    private void LoadProblems()    {        Type[] allProblems = GetDerivedTypesFor(typeof(IProblem)).ToArray();        foreach (Type problem in allProblems)        {            ProblemSelector.Items.Add(FormatName(problem.Name));            IProblem problemInstance = CreateInstanceByName<IProblem>(problem.Name);            problems.Add(problem.Name, problemInstance);        }    }    private string FormatName(string inputString)    {        StringBuilder result = new StringBuilder();        for (int i = 0; i < inputString.Length; i++)        {            if (result.Length > 0)            {                if (char.IsUpper(inputString[i]))                {                    result.Append(' ');                }                else if (i - 1 >= 0 && char.IsNumber(inputString[i]) && char.IsLetter(inputString[i - 1]))                {                    result.Append(' ');                }             }            result.Append(inputString[i]);        }        return result.ToString();    }    private static T CreateInstanceByName<T>(string className)    {        Assembly assembly = Assembly.GetExecutingAssembly();        Type type = assembly.GetTypes().First(t => t.Name == className);        return (T)Activator.CreateInstance(type);    }    private static IEnumerable<Type> GetDerivedTypesFor(Type baseType)    {        Assembly assembly = Assembly.GetExecutingAssembly();        return assembly.GetTypes().Where(baseType.IsAssignableFrom).Where(t => baseType != t);    }    private void button1_Click(object sender, EventArgs e)    {        if (currentProblem != null)        {            ProblemOutput problemOutput;            if (!solvedProblems.ContainsKey(currentProblem.ID))            {                problemOutput = currentProblem.Solve();                solvedProblems.Add(currentProblem.ID, problemOutput);            }            else            {                problemOutput = solvedProblems[currentProblem.ID];            }            ProblemAnswer.Text = problemOutput.OutputText.ToString();            ProblemExecutionTime.Text = problemOutput.ExecutionTime/1000d + @ seconds;        }    }    private void ProblemSelector_SelectedIndexChanged(object sender, EventArgs e)    {        IProblem selectedProblem = problems[Regex.Replace(((Control)sender).Text, @\s+, )];        if (currentProblem == null || selectedProblem.ID != currentProblem.ID)        {            ProblemExecutionTime.Text = string.Empty;            ProblemAnswer.Text = string.Empty;            currentProblem = selectedProblem;            ProblemText.Text = currentProblem.Condition;        }    }}Base interface for all problemspublic interface IProblem{    int ID { get; }    string Condition { get; }    ProblemOutput Solve();}Where ProblemOutput is primarly a wrapper/helper classpublic sealed class ProblemOutput{    private readonly double executionTime;    public double ExecutionTime => executionTime;    private readonly object outputText;    public object OutputText => outputText;    public ProblemOutput(double executionTime, object outputText)    {        this.executionTime = executionTime;        this.outputText = outputText;    }}Here's and example of problem classpublic sealed class Problem1 : IProblem{    public int ID => 1;    public string Condition => ProblemsConditions.ProblemConditions[ID];    public ProblemOutput Solve()    {        int sum = 0;        Stopwatch sw = Stopwatch.StartNew();        for (int i = 1; i < 1000; i++)        {            if (i % 3 == 0 || i % 5 == 0)            {                sum += i;            }        }        sw.Stop();        return new ProblemOutput(sw.ElapsedMilliseconds, sum);    }}Any methods shared between at least 2 problems are grouped in the ProblemHelper classpublic static class ProblemHelper{    private static int GetFactorial(int n)    {        int factorial = 1;        for (int i = 2; i <= n; i++)        {            factorial *= i;        }        return factorial;    }    // some other functions}
Project Euler problem solver in windows forms
c#;object oriented;winforms
[screenshot]Since each problem has an ID, order them by ID before you add them, rather than by name.public partial class Form1 : Form...private void button1_ClickDoesn't matter much here as this is a small program, but I've worked on existing Winforms projects where there were about 100 controls of various sorts all over, and half of them were named button1, label7, things like that. It's ridiculously difficult to know what control you're looking at when you don't rename controls from their defaults. As I said, doesn't matter much for your tiny project, but still a good habit to take on imo.private void LoadProblems()    {        Type[] allProblems = GetDerivedTypesFor(typeof(IProblem)).ToArray();        foreach (Type problem in allProblems)        {            ProblemSelector.Items.Add(FormatName(problem.Name));            IProblem problemInstance = CreateInstanceByName<IProblem>(problem.Name);Style issue, you should go on to define the functions you use under the functions that call them. When I see this method call GetDerivedTypesFor method, I look under the current method to find GetDerivedTypesFor. After all, it's first used by LoadProblems, and the first method it calls. Instead I see FormatName right under this function - why? Then CreateInstanceByName, and finally GetDerivedTypesFor. The order should be:LoadProblemsGetDerivedTypesForFormatNameCreateInstanceByNameThough if for example FormatName calls some function and especially if it's only used by FormatName, then that function should be right after FormatName and before CreateInstanceByName. Basically for the most part (it's not a hard and fast rule but should be the case usually) a function/method should be defined right after its first use.private static T CreateInstanceByName<T>(string className){    Assembly assembly = Assembly.GetExecutingAssembly();    Type type = assembly.GetTypes().First(t => t.Name == className);    return (T)Activator.CreateInstance(type);}I don't really do much reflection, but this seems unnecessary - for every name, you're going to re-get the types and reiterate through them. You already got all the types you wanted in GetDerivedTypesFor, so can't you just create an instance from those types directly?ProblemExecutionTime.Text = problemOutput.ExecutionTime/1000d + @ seconds;You don't need the @ here.private readonly double executionTime;public double ExecutionTime => executionTime;private readonly object outputText;public object OutputText => outputText;I mostly just know .NET 4.0, but I believe your code above uses C# 6.0, so (I believe) you could implement the above like so:public double ExecutionTime { get; }public object OutputText { get; }And then just assign to the property in the constructor.Also why is OutputText an object rather than a string?