Как мне переписать очень большой составной оператор if в C #? - PullRequest
23 голосов
/ 08 июня 2009

В моем коде C # у меня есть выражение if, которое началось достаточно невинно:

if((something == -1) && (somethingelse == -1) && (etc == -1)) {
    // ...
}

Это растет. Я думаю, что сейчас в нем должно быть 20 статей.

Как должен Я справлюсь с этим?

Ответы [ 18 ]

1 голос
/ 08 июня 2009

Еще одна возможность, которую вы можете исследовать, - это использование составных выражений. Эти выражения (которые являются основой работы LINQ в .NET Framework) позволяют создавать деревья выражений на основе всех этих условий, а затем код бизнес-логики может просто работать с выражением верхнего уровня, чтобы получить результат «истина / ложь». .

Для оценки выражений вы можете использовать шаблон посетителя

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

1 голос
/ 08 июня 2009

Я не знаю C #, но, похоже, он включает условный оператор . Если ваши условия короткие, вы можете заменить длинные цепочки if / elsif / else хорошими табличными структурами, например так:

return   something == 0      ? 0
       : somethingelse == -1 ? 1
       : yetanotherthing > 2 ? 2
       :                       3; # default
0 голосов
/ 09 июня 2009

вы говорите, что смотрите на строки, как насчет чего-то подобного, о котором кто-то уже прокомментировал.

        var items = new List<string>();

        items.Add("string1");
        items.Add("string2");

        if (items.Contains("string2"))
        {
            // do something
        }

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

0 голосов
/ 08 июня 2009

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

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

Рефакторинг вашего кода может помочь вам лучше понять его и то, как состояния связаны друг с другом. Я бы начал здесь первым, если бы я был тобой :) 1005 *

0 голосов
/ 08 июня 2009

и как-то так

Я объясню немного дальше. (И исправить глупые ошибки: S)

//Interface to be able to which classes are able to give a boolean result used in the if stuff
public interface IResultable
{
    bool Result();
}

//A list that is IResultable itself it gathers the results of the IResultables inside.
public class ComparatorList<T> : List<T>, IResultable where T : IResultable
{
    public bool Result()
    {
        bool retval = true;
        foreach (T t in this)
        {
            if (!t.Result())
            {
                retval = false;
            }
        }
        return retval;
    }
}

//Or two bools
public class OrComparator : IResultable
{
    bool left;
    bool right;

    public OrComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left || right);
    }

    #endregion
}

// And two bools
public class AndComparator : IResultable
{
    bool left;
    bool right;

    public AndComparator(bool left, bool right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left && right);
    }

    #endregion
}

// compare two ints
public class IntIsComparator : IResultable
{
    int left;
    int right;

    public IntIsComparator(int left, int right)
    {
        this.left = left;
        this.right = right;
    }
    #region IResultable Members

    public bool Result()
    {
        return (left == right);
    }

    #endregion
}

Много ли у вас там заявлений, это может быть круто:)

Итак, у нас есть такая структура для проведения множества сравнений. Я приведу небольшой пример реализации.

//list of ands
ComparatorList<AndComparator> ands = new ComparatorList<AndComparator>();    
ands.Add(new AndComparator(true,true));

//list of ors
ComparatorList<OrComparator> ors = new ComparatorList<OrComparator>();
ors.Add(new OrComparator(false, true));

//list of intiss
ComparatorList<IntIsComparator> ints = new ComparatorList<IntIsComparator>();
ints.Add(new IntIsComparator(1, 1));

//list of all things :)
ComparatorList<IResultable> collected = new ComparatorList<IResultable>();
collected.Add(ands);
collected.Add(ors);
collected.Add(ints);

// if all things are as they must be :)
if (collected.Result())
{
    //Evertything is as it schould be :)
}
0 голосов
/ 08 июня 2009

Я делаю это так, как никто, кроме меня. Мне все равно, если код "выглядит хорошо". Если у меня есть> 1 тест в этом условном выражении, это означает, что я склонен хотеть еще большего, или я могу захотеть прокомментировать некоторые из них, или я хочу упростить внесение таких изменений.

Итак, я пишу это так:

if (true
  && test_1
  && test_2
  ...
  )
{
  ...
}

Это позволяет легко комментировать тесты или добавлять новые в виде однострочных изменений.

Но я буду первым, кто признается, что он не претендует на то, чтобы быть красивым.

0 голосов
/ 08 июня 2009

Хотя мне нравится решение Дарио (как я уже прокомментировал, я бы поместил его в булеву функцию, чтобы у меня не было нового в условии условия if ...) Я не уверен, что не так с:

if((something == -1) &&
   (somethingElse == -1) &&
   (elseElse == -1) &&
   ...
  )

Я думаю, что это, вероятно, намного легче читать, чем много ((A && B) || (C && (D || E))), с которыми мне приходится иметь дело ...

0 голосов
/ 08 июня 2009

Нечасто видеть такое количество предложений в одном «если». Обычно вы обнаруживаете, что вам нужно вложить «если», чтобы получить необходимую логику, когда вам нужно выполнить некоторую строку независимо от истинности некоторых условий. Я не говорю, вкладывайте их, если вам это не нужно, если все они должны быть проверены одновременно. Только если есть какая-то общая функциональность. Другим соображением является установка логической переменной с результатом некоторого набора этих условий, которые могут облегчить понимание. Если ваши переменные являются массивом или коллекцией, можете ли вы пройти через них? Вы тестируете их все против -1?

...