Qual è il modo migliore per aggiornare la variabile booleana in questo particolare scenario? [chiuso]

0

Ho la seguente classe e un metodo chiamato ValidateEverything (), dove IsEverythingValid diventa vero solo quando aob o entrambi sono vere. Mi chiedevo quale sarebbe stato il modo migliore per interrompere il ciclo di foreach. Inoltre, quale sarebbe l'approccio migliore per aggiornare la variabile IsEverythingValid. Supponiamo che le prime tre condizioni if / else-if siano valide.

public class Validator
{
    public bool IsEverythingValid { get; private set; }
    public string ErrorMessage { get; private set; }

    public Validator()
    {
        IsEverythingValid = false;
        ErrorMessage = string.Empty;
    }

    public void ValidateEverything(ID Id)
    {
        var everyThing = SomeOtherClass.GetValues(Id);

        bool a = true;
        bool b = true;

        foreach (Something someThing in everyThing)
        {
            // a = some logic based on the value will be updated
            // b = some logic based on the value will be updated

            if (!a && !b)
                ErrorMessage = "A and B both are messed up";
            else if (!a && !someThing.aAllowed)
                ErrorMessage = "Only A is messed up";
            else if (!b && !someThing.bAllowed)
                ErrorMessage = "Only B is messed up";
            else
                IsEverythingValid = true;

            if(ErrorMessage.Length > 0)
                break;
        }

        if (a || b)
        {
            IsEverythingValid = true;
        }
    }
}

Qualsiasi suggerimento sarebbe davvero utile.

    
posta Sharif Mamun 30.03.2016 - 02:39
fonte

3 risposte

2

Il problema è che stai facendo un sacco di cose da te inutilmente. Stai anche trattando gli intervalli come se fossero valori, ad esempio se imposti un messaggio di errore indipendentemente dal numero di oggetti effettivamente falliti. Un po 'di LINQ gestirà questo facilmente per te.

Prova

var failures = everyThing
               .Select(e => new { a = /* stuff */, b = /* stuff */ })
               .Where(obj => (!obj.a && !obj.aAllowed) || (!obj.b && !obj.bAllowed))
               .ToList();
IsEverythingValid = failures.Count == 0;
ErrorMessage = String.join("\n", failures.Select(obj => /* something */));
    
risposta data 30.03.2016 - 13:46
fonte
0

Puoi semplificare il test per essere:

public void ValidateEverything(ID Id)
{
  var everyThing = SomeOtherClass.GetValues(Id);

  bool a = true;
  bool b = true;

  foreach (Something someThing in everyThing)
  {
    if (someThing.thisIsBroke) 
    {
      a = false;
      break;
    }
    if (someThing.thatIsBroke) 
    {
      b = false;
      break;
    }
  }
  somethingIsValid = a || b;
  everythingIsValid = a && b;
}

L'istruzione break uscirà dal ciclo foreach .

    
risposta data 30.03.2016 - 02:50
fonte
0

what would the best approach to update IsEverythingValid variable.

Nel modo in cui questo è scritto puoi semplicemente rimuovere la prima impostazione di IsEverythingValid. Vedi commenti.

        foreach (Something someThing in everyThing)
        {
            if (!a && !b)
                ErrorMessage = "A and B both are messed up";
            else if (!a && !someThing.aAllowed)
                ErrorMessage = "Only A is messed up";
            else if (!b && !someThing.bAllowed)
                ErrorMessage = "Only B is messed up";
            else
                IsEverythingValid = true;  //<-Pointless, can't get here...
                //ab can get here
                //ff f
                //ft t
                //tf t
                //tt t

            if(ErrorMessage.Length > 0)
                break;
        }

        if (a || b)
        {
            IsEverythingValid = true;  //...without ending up here
            //ab can get here
            //ff f
            //ft t
            //tf t
            //tt t
        }

Il che significa che, indipendentemente da everyThing , non stai convalidando nient'altro che a e b.

what would be the best way to break the foreach loop

Non questo.

Considera cosa succede al tuo codice e ai tuoi messaggi di errore se devi aggiungere un c che deve essere convalidato. Pensi che sia male? Prova ad aggiungere anche d .

Ogni riga che ora devi modificare è un posto in cui inserire i bug. Preferirei un design che fosse leggermente più tollerante ai cambiamenti.

Tendo a lasciare codice di convalida nella classe che deve essere convalidato. Non creo una classe Validator.

Quello che faccio è avere un metodo di validazione nella classe che chiamo quando la classe dovrebbe essere valida. Questo permesso mi permette di usare setter senza preoccuparmi che la classe possa essere lasciata in cattive condizioni, perché, diciamo, non tutti i setter sono stati chiamati prima che qualcuno provasse a usarlo. Io custodisco l'uso della classe con una chiamata a validare () prima di consentire che qualsiasi cosa venga eseguita con la classe oltre a chiamare i setter.

Ma sembra che tu stia facendo qualcos'altro. La segnalazione di ErrorMessage sta causando problemi perché hai consentito solo un messaggio di errore. Hai distorto la tua logica in nodi cercando di soddisfare la necessità di riflettere il tuo stato con un solo messaggio.

Considera questo:

     public bool IsEverythingValid
     {
         get { return (ValidateEverything().Length == 0); }
     }

     public string ValidateEverything(ID Id)
     {
        ErrorMessage = string.Empty;
        var everyThing = SomeOtherClass.GetValues(Id);

        bool a = true;
        bool b = true;

        foreach (Something someThing in everyThing)
        {
            if (!a && !someThing.aAllowed)
                ErrorMessage += "A is messed up on " + someThing.name + Environment.NewLine;
            if (!b && !someThing.bAllowed)
                ErrorMessage += "B is messed up on " + someThing.name + Environment.NewLine;

            return ErrorMessage;
        }
     }

Ora stai segnalando lo stato completamente con il tuo messaggio. Aggiungere c o d non sarebbe difficile. Non stai impostando IsEverythingValid su un valore e lascia che il mondo cambi intorno a te senza aggiornarlo prima di segnalarlo.

    
risposta data 30.03.2016 - 08:02
fonte

Leggi altre domande sui tag