C# - Расчеты как объекты - Множество вычислений с множеством зависимостей - PullRequest
2 голосов
/ 10 марта 2020

Я разработал довольно сложную электронную таблицу в Excel, и мне поручено преобразовать ее в программу C#.

Я пытаюсь выяснить, как представлять вычисления из моей электронной таблицы в C#.

Расчеты имеют много зависимостей, вплоть до того, что они кажутся почти веб-сетью, а не красивой аккуратной иерархией.

Я могу придумать решение для проектирования: this:

  • Создайте объект для представления каждого вычисления.
  • Каждый объект имеет целое или двойное число, которое содержит вычисление. этот cal c имеет входные данные от других объектов и поэтому требует, чтобы они были оценены сначала, прежде чем он может быть выполнен.

  • Каждый объект имеет второе целое число "завершено «, который оценивается как 1, если предыдущий расчет был успешным

  • У каждого объекта есть третье целое число« готово » Для этого элемента требуется целое число всех прецедентных объектов« завершено » rs оценивается как "1", а если нет, то l oop пропускает этот объект
  • AL oop пробегает все объекты, пока все "завершенные" целые числа = 1

Надеюсь, это имеет смысл. Я набираю код для этого, но я все еще довольно зеленый с C#, так что, по крайней мере, зная, что я на правильном пути, это благо :) Чтобы уточнить, это запрос дизайна, я просто ищу кого-то более опытный с C#, чем я, чтобы убедиться, что мой метод разумен.

Я ценю любую помощь в этом вопросе, и мне очень хотелось бы услышать ваши мысли! :)

edit *

Я считаю, что для проверки состояния l oop необходимы состояние «завершено» и «готово», чтобы избежать ошибок, которые могут возникнуть при попытках оценки вычисления где прецеденты не оцениваются. Это необходимо?

У меня установлено значение «Любой ЦП», настройка по умолчанию.

edit *

Например, одним объектом будет строка «V_dist» Он имеет длину, как свойство. Его длина "V_dist.calc_formula" рассчитывается по двум другим объектам: "hp c* Tan (dang)" *

public class inputs
{
    public string input_name;
    public int input_angle;
    public int input_length;
}
public class calculations
{
    public string calc_name; ///calculation name
    public string calc_formula; ///this is just a string containing formula
    public double calculationdoub; ///this is the calculation
    public int completed; ///this will be set to 1 when "calculationdoub" is nonzero
    public int ready; ///this will be set to 1 when dependent object's "completed" property = 1
}
public class Program
{
    public static void Main()
    {
        ///Horizontal Length
        inputs hpc = new inputs();
        hpc.input_name = "Horizontal "P" Length";
        hpc.input_angle = 0;
        hpc.input_length = 200000;

        ///Discharge Angle
        inputs dang = new inputs();
        dang.input_name = "Discharge Angle";
        dang.input_angle = 12;
        dang.input_length = 0;

        ///First calculation object
        calculations V_dist = new calculations();
        V_dist.calc_name = "Vertical distance using discharge angle";
        V_dist.calc_formula = "hpc*Tan(dang)";
        **V_dist.calculationdoub = inputs.hpc.length * Math.Tan(inputs.dang.input_angle);**
        V_dist.completed = 0;
        V_dist.ready = 0;
    }
}

. Следует отметить, что другие функции, которые мне еще предстоит добавить, такие как l oop и logi c, управляющие двумя логическими свойствами

1 Ответ

0 голосов
/ 12 марта 2020

У вас есть хорошие идеи, но если я понимаю, что вы пытаетесь сделать, я думаю, что есть более идиоматический c - более OOP способ решить эту проблему, который также гораздо менее сложен. Я предполагаю, что у вас есть стандартная электронная таблица, в которой есть много строк в электронной таблице, которые все имеют одинаковые столбцы. Также могут быть разные столбцы в разных разделах электронной таблицы.

Я преобразовал несколько электронных таблиц в приложения и остановился на этом подходе. Я думаю, вам понравится.

Для каждого набора заголовков я бы смоделировал это как отдельный объектный класс. Каждый столбец будет свойством класса, и каждая строка будет одним экземпляром объекта.

Во всех, кроме очень редких случаях, я бы сказал, просто смоделируйте ваши свойства, чтобы включить вычисления. Простой пример c блока будет выглядеть примерно так:

public class Box
{
    public double Length { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area
    {
        get { return 2*Height*Width + 2*Length*Height + 2*Length*Width; }
    }

    public double Volume
    {
        get { return Length * Width * Height; }
    }
}

И идея здесь в том, что если есть свойства (столбцы в Excel), которые используют другие вычисляемые свойства / столбцы в качестве входных данных, просто используйте само свойство:

public bool IsHuge
{
    get { return Volume > 50; }
}

. NET будет обрабатывать все тяжелые работы и зависимости для вас.

В большинстве случаев это вылетит в C# по сравнению с Excel, и я не думаю, что вам придется беспокоиться о скорости вычислений при настройке каскадных объектов.

Когда я говорил о всех, кроме редких случаях, если у вас есть свойства, которые очень дорогие в вычислительном отношении затем вы можете сделать эти свойства частными и затем запустить вычисления.

public class Box
{
    public double Length { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public double Area { get; private set; }
    public double Volume { get; private set; }
    public bool IsHuge { get; private set; }

    public void Calculate()
    {
        Area = 2*Height*Width + 2*Length*Height + 2*Length*Width;
        Volume = Length * Width * Height;
        IsHuge = Volume > 50;
    }
}

Прежде чем вы go пойдете по этому пути, я бы порекомендовал вам провести тестирование производительности. Если у вас нет миллионов строк и / или очень сложных вычислений, я сомневаюсь, что этот второй подход был бы полезен, и у вас есть преимущество в том, что вам не нужно определять, когда вычислять. Это происходит, когда и только когда к объекту обращаются.

...