C# как сократить несколько выражений If - PullRequest
8 голосов
/ 27 мая 2020

У меня есть несколько логических свойств проверки, которые могут потребоваться или нет. Если они необходимы, их необходимо проверить для целей валидации. Поэтому мне пришлось создать несколько операторов if для обработки каждого свойства. Мой вопрос: есть ли лучший способ сохранить это, вместо того, чтобы писать if для каждого нового свойства.

public class ProductionNavbarViewModel
{
    public bool IsProductionActive { get; set; }
    public bool ValidatedComponents { get; set; }
    public bool ValidatedGeometries { get; set; }
    public bool ValidatedPokayokes { get; set; }
    public bool ValidatedTechnicalFile { get; set; }
    public bool ValidatedStandardOperationSheet { get; set; }
    public bool ValidatedOperationMethod { get; set; }
    public bool IsComponentsRequired { get; set; }
    public bool IsGeometriesRequired { get; set; }
    public bool IsPokayokesRequired { get; set; }
    public bool IsTechnicalFileRequired { get; set; }
    public bool IsStandardOperationSheetRequired { get; set; }
    public bool IsOperationMethodRequired { get; set; }


    public bool IsProductionReadyToStart()
    {
        if (IsComponentsRequired)
        {
            return ValidatedComponents;
        }

        if (IsComponentsRequired && IsGeometriesRequired)
        {
            return ValidatedComponents && ValidatedGeometries;
        }

        if (IsComponentsRequired && IsGeometriesRequired && IsPokayokesRequired)
        {
            return ValidatedComponents && ValidatedGeometries && ValidatedPokayokes;
        }

        if (IsComponentsRequired && IsGeometriesRequired && IsPokayokesRequired && IsTechnicalFileRequired)
        {
            return ValidatedComponents && ValidatedGeometries && ValidatedPokayokes && ValidatedTechnicalFile;
        }

        if (IsComponentsRequired && IsGeometriesRequired && IsPokayokesRequired && IsTechnicalFileRequired && ValidatedStandardOperationSheet)
        {
            return ValidatedComponents && ValidatedGeometries && ValidatedPokayokes && ValidatedTechnicalFile && ValidatedStandardOperationSheet;
        }

        if (IsComponentsRequired && IsGeometriesRequired && IsPokayokesRequired && IsTechnicalFileRequired && IsStandardOperationSheetRequired && IsOperationMethodRequired)
        {
            return ValidatedComponents && ValidatedGeometries && ValidatedPokayokes && ValidatedTechnicalFile && ValidatedStandardOperationSheet && ValidatedOperationMethod;
        }

        return false;
    }
}

EDIT

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

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

ОБНОВЛЕНИЕ

Я пришел с короткой версией на данный момент и более удобочитаемой на основе всех комментариев, пока я не смогу попробовать все подходы. Отредактировано для объединения всех выражений в соответствии с ответом @Alexander Powolozki.

    public bool IsProductionReadyToStart()
    {
        bool isValid = true;

        isValid &= !IsComponentsRequired || ValidatedComponents;
        isValid &= !IsGeometriesRequired || ValidatedGeometries;
        isValid &= !IsPokayokesRequired || ValidatedComponents;
        isValid &= !IsTechnicalFileRequired || ValidatedTechnicalFile;
        isValid &= !IsStandardOperationSheetRequired || ValidatedStandardOperationSheet;
        isValid &= !IsOperationMethodRequired || ValidatedOperationMethod;            

        return isValid;
    }

Ответы [ 6 ]

7 голосов
/ 27 мая 2020

Похоже на коллекцию

public class Validation
{
    public bool Required { get; set; }
    public bool IsValid { get; set; }
}

var validations = new[]
{
    new Validation { Required = true, IsValid = true },
    new Validation { Required = false, IsValid = true },
    new Validation { Required = true, IsValid = false },
};

// return true only when all required validations are valid
public bool IsProductionReadyToStart()
{
    return _validations.Where(v => v.Required).All(v => v.IsValid);
}
7 голосов
/ 27 мая 2020

Правильная реализация метода должна выглядеть примерно так:

public bool IsProductionReadyToStart()
{
    bool isValid = true;

    isValid &= !IsComponentsRequired || ValidatedComponents;
    isValid &= !IsGeometriesRequired || ValidatedGeometries;
    isValid &= !IsPokayokesRequired || ValidatedPokayokes;
    isValid &= !IsTechnicalFileRequired || ValidatedTechnicalFile;
    isValid &= !IsStandardOperationSheetRequired || ValidatedStandardOperationSheet;
    isValid &= !IsOperationMethodRequired || ValidatedOperationMethod;            

    return isValid;
}

если вы не используете & =, вы стираете все предыдущие результаты, которые вы проверили, вместо их объединения.

5 голосов
/ 27 мая 2020

Вы можете собрать свои условия в коллекцию ValueTuple, а затем проверить их все вместе

var conditions = new[]
{
    (IsComponentsRequired, ValidatedComponents),
    (IsGeometriesRequired, ValidatedGeometries),
    (IsPokayokesRequired, ValidatedPokayokes)
};

return conditions.Where(c => c.Item1).All(c => c.Item2);

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

var conditions = new (bool isRequired, bool validated)[]
{
    (IsComponentsRequired, ValidatedComponents),
    (IsGeometriesRequired, ValidatedGeometries),
    (IsPokayokesRequired, ValidatedPokayokes)
};

return conditions.Where(c => c.isRequired).All(c => c.validated);
5 голосов
/ 27 мая 2020

Я бы go с:

if (IsComponentsRequired && !ValidateComponents) return false;
if (IsGeometriesRequired && !ValidatedGeometries) return false;
...
return true;

Это больше похоже на контрольный список.

3 голосов
/ 27 мая 2020

Мне нравится использовать &=, он выглядит довольно чистым, но недостатком является то, что не все знакомы с этим подходом.


bool result = true;

result &= !IsComponentsRequired || IsComponentsRequired && ValidatedComponents;
result &= !IsGeometriesRequired|| IsGeometriesRequired && ValidatedGeometries;
//...etc
return result;

Этот код будет работать так же, как:

result = result && (!IsComponentsRequired || IsComponentsRequired && ValidatedComponents);
//...etc

Но я думаю, что побитовая операция выглядит чище.

1 голос
/ 27 мая 2020

Думаю, вам действительно нужно следующее:

return 
    (IsComponentsRequired && ValidatedComponents || IsComponentsRequired == false) &&
    (IsGeometriesRequired && ValidatedGeometries) || IsGeometriesRequired == false) &&
    (IsPokayokesRequired && ValidatedPokayokes || IsPokayokesRequired == false ) &&
    (IsTechnicalFileRequired && ValidatedTechnicalFile ||  IsTechnicalFileRequired == false) &&
    (IsStandardOperationSheetRequired && ValidatedStandardOperationSheet || IsTechnicalFileRequired == false) &&
    (IsOperationMethodRequired && ValidatedOperationMethod || IsOperationMethodRequired == false )

Это можно реализовать с помощью отражения, поэтому вам не нужно менять код при добавлении дополнительных свойств:

public class ProductionNavbarViewModel
{
    public bool IsProductionActive { get; set; }
    public bool ValidatedComponents { get; set; }
    public bool ValidatedGeometries { get; set; }
    public bool ValidatedPokayokes { get; set; }
    public bool ValidatedTechnicalFile { get; set; }
    public bool ValidatedStandardOperationSheet { get; set; }
    public bool ValidatedOperationMethod { get; set; }
    public bool IsComponentsRequired { get; set; }
    public bool IsGeometriesRequired { get; set; }
    public bool IsPokayokesRequired { get; set; }
    public bool IsTechnicalFileRequired { get; set; }
    public bool IsStandardOperationSheetRequired { get; set; }
    public bool IsOperationMethodRequired { get; set; }


    public bool IsProductionReadyToStart()
    {
        var validatedProps = this.GetType().GetProperties().Where(x => x.Name.StartsWith("Validated"));
        foreach (var validatedProp in validatedProps)
        {
            var concept = validatedProp.Name.Substring(9);
            var isRequiredProp = this.GetType().GetProperty("Is" + concept + "Required");
            var isRequired = (bool)isRequiredProp.GetValue(this);
            if (isRequired)
            {
                var isValid = (bool)validatedProp.GetValue(this);
                if (isValid == false) return false;
            }
        }
        return true;
    }
}
...