Verifica se un metodo restituisce false: assegnare il risultato alla variabile temporanea o mettere la chiamata del metodo direttamente in condizione?


9

È buona norma chiamare un metodo che restituisce valori veri o falsi in un'istruzione if?

Qualcosa come questo:

private void VerifyAccount()
{
    if (!ValidateCredentials(txtUser.Text, txtPassword.Text))
    {
        MessageBox.Show("Invalid user name or password");
    }
}

private bool ValidateCredentials(string userName, string password)
{
    string existingPassword = GetUserPassword(userName);
    if (existingPassword == null)
        return false;

    var hasher = new Hasher { SaltSize = 16 };
    bool passwordsMatch = hasher.CompareStringToHash(password, existingPassword);

    return passwordsMatch;
}

o è meglio memorizzarli in una variabile e confrontarli usando if else valori come questo

bool validate = ValidateCredentials(txtUser.Text, txtPassword.Text);
if(validate == false){
    //Do something
}

Non mi riferisco solo a .NET, mi riferisco alla domanda in tutti i linguaggi di programmazione, solo che succede che ho usato .NET come esempio


3
Se si utilizza una variabile temporanea, scrivere if (!validate)anziché if (validate == false).
Filippo,

12
Vorrei nominare la funzione qualcosa come "CredentialsAreValid ()", quindi sai che dovrebbe restituire un bool ma altrimenti sì, è una buona pratica
Zachary K

3
IsValidCredentials, sebbene grammaticalmente imbarazzante, è un formato comune per indicare un valore di ritorno booleano.
zzzzBov,

@Philip qual è la differenza tra if (! Validate) e this if (validate) ??
KyelJmD,

!è l'operatore "NOT", annulla qualsiasi espressione booleana. Quindi if (!validate)è l'opposto di if (validate). L'istruzione if verrà inserita se validatenon è vera.
Filippo,

Risposte:


26

Come per tutte queste cose dipende.

Se non hai intenzione di utilizzare il risultato della tua chiamata ValidateCredentials, non è necessario (se non per scopi di debug) archiviare il risultato in una variabile locale. Tuttavia, se rende il codice più leggibile (e quindi più gestibile) per avere una variabile andare con quello.

Il codice non sarà misurabile in modo meno efficiente.


1
è quel tipo di leggibile? come quello che ho fatto sopra
KyelJmD il

@KyelJmD: dipende dalla cultura in cui stai programmando. Nei luoghi in cui ho programmato, !ValidateCredentialsè più leggibile perché dice esplicitamente cosa sta facendo nel codice. È molto chiaro Se la funzione che stai chiamando non ha un nome "auto-documentante", potrebbe essere meglio usare la variabile. Allo stato attuale, consiglierei di omettere la variabile e di rimanere con il codice di auto-documentazione che hai.
Joel Etherton,

ValidateCredentials non è leggibile in primo luogo - come fa il nome a dirti cosa significa il risultato? Molto meglio CredentialsAreValid o CredentialsAreInvalid.
gnasher729,

9

Perché usare una variabile aggiuntiva? Preferisco usare il primo approccio, è più leggibile e semplice.


4

È buona norma chiamare un metodo che restituisce valori veri o falsi in un'istruzione if?

Sì, se il condizionale non è abbastanza semplice da incorporare e renderlo leggibile.

o è meglio memorizzarli in una variabile e confrontarli usando if else valori come questo

Dovresti farlo solo se stai usando il valore in più posizioni o ne hai bisogno per rendere il codice più leggibile. Altrimenti l'assegnazione a una variabile non è necessaria. Il codice non necessario è, nella migliore delle ipotesi, dispendioso e nella peggiore delle ipotesi fonte di un difetto.


2

Vediamo...

Perché è tutto su KISS , non è necessario creare una variabile aggiuntiva quando puoi farne a meno. Inoltre, non è necessario digitare altro ... quando non è necessario.

Ma poi, poiché sei ASCIUTTO , se in seguito ti stavi chiamando ValidateCredentialse ti accorgessi ValidateCredentials(txtUser.Text, txtPassword.Text)di digitare , sapevi che avresti dovuto creare una variabile aggiuntiva.


2

Sì, di solito va bene usare metodi come se le condizioni. È utile se il nome del metodo indica che il metodo restituisce un valore booleano; ad esempio CanValidateCredentials. Nei linguaggi in stile C questo metodo spesso assume la forma dei prefissi Is e Can e in Ruby con il simbolo "?" suffisso.


1
Un buon punto sui nomi dei metodi, ma non inizierei mai un nome di metodo con "if". Quindi il codice legge "if if". "Can" è ok: if (cat.canOpenCanOfCatFood()).
Kevin Cline,

Grazie, @Kevin. Intendevo "Is" non "If". Ho modificato la risposta
Christian Horsdal,

1

C'è un'altra preoccupazione che non è stata ancora sottolineata: valutazione del corto circuito . Qual è la differenza tra questi due frammenti di codice?

Ex n. 1:

if(foo() && bar() && baz())
{
    quz();
}

Ex # 2:

bool isFoo = foo();
bool isBar = bar();
bool isBaz = baz();
if(isFoo && isBar && isBaz)
{
    quz();
}

Questi due frammenti di codice sembrano fare la stessa cosa, ma se la tua lingua supporta la valutazione del corto circuito, questi due frammenti sono diversi. La valutazione del corto circuito indica che il codice valuterà il minimo necessario per superare o fallire una condizione. Se l'esempio n. 1, se foo () restituisce false, bar () e baz () non vengono nemmeno valutati. Ciò è utile se baz () è una chiamata di funzione a esecuzione prolungata perché è possibile saltarla se foo () restituisce false o foo () restituisce true e bar () restituisce false.

Questo non è il caso nell'esempio n. 2. foo (), bar () e baz () vengono sempre valutati. Se ti aspetti che bar () e baz () mostrino effetti collaterali, avrai problemi con l'esempio n. 1. L'esempio n. 1 sopra è effettivamente equivalente a questo:

Ex n. 3:

if(foo())
{
    if(bar())
    {
        if(baz())
        {
            quz();
        }
    }
}

Fai attenzione a queste differenze nel tuo codice quando scegli tra gli esempi 1 e 2.


1

Espandendo un po 'il problema della leggibilità ...

Posso pensare a due buoni motivi per memorizzare il risultato in una variabile:

  1. Se utilizzerai la condizione più di una volta, salvarla in una variabile significa che devi chiamare la funzione solo una volta. (Ciò presuppone che il valore memorizzato sia ancora valido; se è necessario riprovarlo, ovviamente questo non si applica.)

  2. Se la memorizzazione in una variabile migliora la leggibilità, assegnando alla condizione un nome più significativo di quello visualizzato nella chiamata di funzione.

Ad esempio, questo:

bool foo_is_ok = is_ok(foo);
if (foo_is_ok) ...

non aiuta la leggibilità, ma questo:

bool done_processing = feof(file1) && feof(file2);
if (done_processing) ...

probabilmente lo fa, poiché non è immediatamente ovvio ciò feof(file1) && feof(file2)significa che abbiamo terminato l'elaborazione.

La passwordsMatchvariabile nella domanda è probabilmente un esempio migliore del mio.

Le variabili monouso sono utili se danno un nome significativo a un valore. (Questo è ovviamente a beneficio del lettore umano.)


Penso che preferirei rilasciare un commento invece di introdurre la done_processingvariabile. Dopotutto, il nome ha done_processingla funzione di un commento. E un vero commento mi permette di dire una o due parole sul perché questa condizione segnala che abbiamo terminato l'elaborazione. Non che io sia un grande commentatore, però, probabilmente non farei nessuno dei due in codice reale ...
cmaster - reinstalla monica il

@cmaster: un problema con i commenti è che possono facilmente sincronizzarsi con il codice. Una variabile denominata done_processingè un modo più durevole di esprimere l'intento.
Keith Thompson,

+1 per il punto numero 2 - a volte un var var ben definito chiarisce davvero le cose.
user949300,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.