2009-05-27 10 views
22

In JavaScript c'è l'idea di valori di verità e di falsità.C# valori di verità e falsi

ad es.

  • 0: sempre false
  • 1: sempre vero
  • '0': sempre vero
  • '1': sempre vero

Esiste un elenco equivalente di truthy e Falsey valori nel linguaggio C# sul framework .NET?

Il motivo che mi piacerebbe sapere questo è che mi ritrovo a fare la seguente

if(obj != null) 
{ 
    // Do something with the object 
} 

Quando ho potuto scrivere il seguente

if(obj) 
{ 
    // Do something with the object 
} 

risposta

38

C# ha solo valori letterali true e false.

C# richiede di essere molto esplicito nelle dichiarazioni poiché è un linguaggio fortemente tipizzato, al contrario di JavaScript che può eseguire conversioni implicite quando necessario.

È importante notare che "la digitazione forte" non è la ragione per cui C# non converte implicitamente in valori "verità/falsi". Il linguaggio sta cercando intenzionalmente di evitare le insidie ​​di altri linguaggi compilati come il C++ dove certi valori possono essere veritieri, come '0' o '1' che potrebbero permetterti di fare un errore sintattico che potresti non notare fino al runtime quando il tuo codice si comporta inaspettatamente .

+1

Ok immagino che risponda alla mia domanda :) – Alex

+5

Quindi tutti voi dinosauri potete smettere di scrivere se (0 == i) ... – Benjol

+1

-1; ci sono alcuni problemi qui. In primo luogo, stai abusando del termine "letterale" nella tua prima frase; un'espressione che non è un valore letterale può ancora essere un valore booleano (ad esempio '1 == 1'). In secondo luogo, l'affermazione secondo cui nulla è vero o falso, ad eccezione dei booleani, è falsa, come già trattata da altre risposte. In terzo luogo, l'inizio del terzo paragrafo non ha molto senso. Una mancanza di conversione implicita è la * definizione * della tipizzazione forte (o almeno la più comune - è un termine un po 'nebuloso e sovraccarico); stai effettivamente dicendo che una forte digitazione non è la ragione per se stessa, il che è strano. –

0

Se obj è un tipo che si è creato, è può definire una conversione implicita definita dall'utente in bool.

+1

Non lo consiglierei come "best practice" ... – dtb

+0

Neanche io! Questo è l'unico modo che conosco per ottenere la sintassi che Alex sta chiedendo. –

13

Risposta breve:

In C#:

  • vero: sempre vero
  • falso: sempre falso

Tutto il resto non è un valore booleano.

+0

Non vero. Vedi la mia risposta qui sotto. – Trumpi

+0

La mia risposta non contraddice il tuo. I tipi possono implementare conversioni implicite su bool o sul tuo operatore 'vero', ma qualsiasi valore di tale tipo non è ancora di tipo 'bool' :) – dtb

+0

Ho letto di nuovo la tua risposta: in realtà contraddice le specifiche. – Trumpi

3

L'istruzione if valuta qualcosa che può essere convertito in/equivale a/ritorna booleano, o un valore booleano per sé ... il controllo di nulla come obj! = Null è una tale espressione,

'if (obj) 'può funzionare se solo se obj è in grado di convertire in bool, non se è nullo.

-4

C# è un linguaggio tipizzato staticamente, vale a dire che il tipo di oggetti è importante nell'impostazione di ciò che è.

Ad esempio, "4"! = 4.

JavaScript, tuttavia è un linguaggio dinamicamente tipizzato, in modo che i tipi hanno poca importanza.

Così in JavaScript, "4" == 4.

I valori "truthy" sono valori che capita di soddisfare x == true, mentre i valori "Falsey" non lo fanno.

Senza la sicurezza del tipo, alcune funzionalità come il sovraccarico producono comportamenti imprevedibili.

Per ulteriori informazioni, è possibile vedere here.

+3

No, la digitazione dinamica di V statica non ha nulla a che fare con questo. –

10

Codice come quello (e dovrebbe) non riuscire a compilare. Se si desidera in particolare ignorare tale comportamento, è possibile creare un valore booleano da implicit conversion. Qualcosa di simile a questo:

public class Foo { 
    public static implicit operator bool(Foo me) { 
     if (me == null) { 
      return false; 
     } 

     return true; // maybe add more logic before saying True 
    } 
} 

che definirei che una cattiva pratica perché, per un programmatore che non hanno familiarità con il progetto, non è immediatamente chiaro che cosa logica alimenta la conversione booleano. Il modo più idiomatico per farlo sarebbe quello di dire esplicitamente al lettore ciò che il codice sta facendo, come il costruito in classe String fa, con una funzione di supporto statica:

if (String.IsNullOrEmpty(str){ 
    // ... 
} 

codice è scritto solo una volta, e leggere spesso ; ottimizzare per la leggibilità.

+0

+1 (00000 se possibile) per menzionare la leggibilità e la comprensibilità. La logica implicita in troppi posti può uccidere i progetti. – Phil

15

La risposta corretta alla tua domanda si trova nella sezione 7.19 della specifica C# 3.0, che puoi trovare facilmente su Internet. Per la vostra comodità, il testo di riferimento è:

7,19 espressioni booleane

A booleana espressione è un'espressione che produce un risultato di tipo bool.

L'espressione condizionale di controllo di un'istruzione if [...] è un'espressione booleana . [...]

A booleana espressione è necessaria per essere di un tipo che può essere implicitamente convertito in bool o di un tipo che implementa operatore vero. Se non è soddisfatto né il requisito , si verifica un errore in fase di compilazione .

Quando un'espressione booleana è di un tipo che non può essere convertito in modo implicito bool ma non attuare operatore vero, poi seguendo valutazione della espressione, l'operatore vero attuazione offerto da tale tipo viene richiamato per produrre un valore bool.

ci sono tipi diversi bool sé che sono implicitamente convertibile bool tramite una conversione incorporato, ma naturalmente, conversioni implicite definiti dall'utente per bool può essere definito dall'utente.

20

Per impostazione predefinita, C# fornisce solo true e false.

Tuttavia, è possibile impostare i propri tipi personalizzati "veritieri" e "falsi" implementando l'operatore true. Quando un tipo implementa l'operatore true, le istanze di quel tipo possono essere utilizzate come espressioni booleane. Dalla sezione 7.19 della C# Language Specification:

Quando un'espressione booleana è di un tipo che non può essere convertito in modo implicito bool ma non attuare operatore vero, poi seguendo valutazione dell'espressione, l'operatore vero attuazione offerto da questo tipo viene richiamato per produrre un valore bool.

Il tipo di struttura DBBool in §11.4.2 fornisce un esempio di un tipo che implementa l'operatore true e l'operatore false.

Ecco un frammento di codice di una dichiarazione dell'operatore true (che probabilmente compiere ciò che si voleva fare nella tua domanda):

public static bool operator true(MyType myInstance) 
{ 
    return myInstance != null; 
} 

se si implementa l'operatore true, allora è necessario implementare anche l'operatore false.

+5

Questa è la risposta corretta. Tutte le risposte che non menzionano i falsi sovraccarichi dell'operatore vero/operatore sono alquanto incomplete.È anche corretto che ciò che l'OP sta tentando di fare non è davvero una buona idea, ma questo è il modo migliore per farlo. –

+0

Se si implementa l'operatore vero, è necessario implementare anche l'operatore falso. -> questo è strano Non dovrebbe essere sempre il risultato dell'operatore falso (vero operatore) ??! – David

+0

Mi sembra che sarebbe generalmente preferibile implementare una conversione implicita in bool piuttosto che negli operatori 'true' e' false', no? Un metodo invece di due e nessuna possibilità di commettere un errore in cui i due metodi sono incoerenti tra loro. –

1

Le risposte precedenti sono corrette. Tuttavia, ho un metodo di estensione che uso in alcuni rari casi:

public static bool IsTruthy(this object obj) 
{ 
    if (obj == null || obj is DBNull) 
     return false; 

    var str = obj as string; 
    if (str != null) 
     return !string.IsNullOrWhiteSpace(str) && 
      !str.Trim().Equals(bool.FalseString, StringComparison.OrdinalIgnoreCase); 

    try 
    { 
     if (Convert.ToDecimal(obj) == 0) 
      return false; 
    } 
    catch { } 

    if (obj is BigInteger) 
     return ((BigInteger)obj) != 0; 

    return true; 
} 

Alcune note su questo:

  • Questo metodo non è coerente con il modo in javascript gestisce la stringa "False"
  • Questo metodo restituisce true per le enumerables vuote, che è coerente con javascript
+0

'che uso in alcuni rari casi'. Puoi dare alcuni esempi di quando hai bisogno di usare Truthy, Falsey controlla in C#. Non ho mai sentito di qualcuno che abbia bisogno di questo nel mondo .Net di sempre. – Shiva

+0

Non riesco a ricordare e la ricerca nella mia cartella di codice non ha restituito nulla. Sembra difficile da immaginare, ma sono sicuro che ho avuto le mie ragioni. ¯ \ _ (ツ) _/¯ –

0

È possibile definire la propria verità e falsità mediante i metodi di estensione.

public static bool Falsy(this object obj) { 
     if(obj == null) return true; 
     if (obj is string) 
      if(obj as string == string.Empty) return true; 
     if(obj is byte) 
      if((byte)obj == 0) return true; 
     if(obj is sbyte) 
      if((sbyte)obj == 0) return true; 
     if(obj is short) 
      if((short)obj == 0) return true; 
     if(obj is ushort) 
      if((ushort)obj == 0) return true; 
     if(obj is int)    
      if((int)obj == 0) return true; 
     if(obj is uint) 
      if((uint)obj == 0) return true; 
     if(obj is long) 
      if((long)obj == 0) return true; 
     if(obj is ulong) 
      if((ulong)obj == 0) return true; 
     if(obj is float) 
      if((float)obj == 0) return true; 
     if(obj is double) 
      if((double)obj == 0) return true; 
     if(obj is decimal) 
      if((decimal)obj == 0) return true; 
     if(obj is IEnumerable<object>) 
      if((obj as IEnumerable<object>).Count<object>() == 0) 
       return true; 
     if(obj is Array) 
      if(((Array)obj).Length <= 0) 
       return true; 
     if(obj is ObjectId) 
      if(((ObjectId)obj).Pid == 0) return true; 
     if(obj is System.Collections.ObjectModel.ObservableCollection<M>) 
      if(((ObservableCollection<M>)obj).Count <= 0) return true; 
       return false; 
} 

public static bool Truthy(this object obj) { 
    return !Falsy(obj); 
} 

Così si può fare qualcosa di simile:

se (customerList.Falsy()) {throw new Exception ("Non può essere nullo o vuoto"); }

Problemi correlati