A cosa serve il falso operatore in C #?

Ci sono due operatori strani in C #:

  • il vero operatore
  • il falso operatore

Se capisco bene, questi operatori possono essere usati nei tipi che voglio usare al posto di un’espressione booleana e dove non voglio fornire una conversione implicita al bool.

Diciamo che ho una class seguente:

public class MyType { public readonly int Value; public MyType(int value) { Value = value; } public static bool operator true (MyType mt) { return mt.Value > 0; } public static bool operator false (MyType mt) { return mt.Value < 0; } } 

Quindi posso scrivere il seguente codice:

  MyType mTrue = new MyType(100); MyType mFalse = new MyType(-100); MyType mDontKnow = new MyType(0); if (mTrue) { // Do something. } while (mFalse) { // Do something else. } do { // Another code comes here. } while (mDontKnow) 

Tuttavia, per tutti gli esempi precedenti, viene eseguito solo l’operatore vero. Quindi a cosa serve il falso operatore in C #?

Nota: altri esempi possono essere trovati qui , qui e qui .

Puoi usarlo per sovrascrivere il && e || operatori.

Il && e || gli operatori non possono essere sostituiti, ma se si esegue l’override | , & , true e false nel modo esatto in cui il compilatore chiamerà | e & quando scrivi || e && .

Ad esempio, guarda questo codice (da http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading – dove ho scoperto questo trucco, versione archiviata da @BiggsTRC):

 public static AbstractCriterion operator &(AbstractCriterion lhs, AbstractCriterion rhs) { return new AndExpression(lhs, rhs); } public static AbstractCriterion operator |(AbstractCriterion lhs, AbstractCriterion rhs) { return new OrExpression(lhs, rhs); } public static bool operator false(AbstractCriterion criteria) { return false; } public static bool operator true(AbstractCriterion criteria) { return false; } 

Questo è ovviamente un effetto collaterale e non il modo in cui è destinato a essere usato, ma è utile.

Shog9 e Nir: grazie per le vostre risposte. Queste risposte mi hanno indirizzato verso l’ articolo di Steve Eichert e mi ha indirizzato a msdn :

L’operazione x && y è valutata come T.false (x)? x: T. & (x, y), dove T.false (x) è una chiamata dell’operatore false dichiarato in T, e T. & (x, y) è una chiamata dell’operatore selezionato &. In altre parole, x viene prima valutato e l’operatore false viene invocato sul risultato per determinare se x è definitivamente falso. Quindi, se x è definitivamente falso, il risultato dell’operazione è il valore precedentemente calcolato per x. Altrimenti, y viene valutato e l’operatore selezionato viene richiamato sul valore precedentemente calcolato per x e il valore calcolato per y per produrre il risultato dell’operazione.

La pagina che si collega a http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx dice a cosa servivano, che era un modo di gestire i bool nullable prima che fossero introdotti i tipi di valori nullable.

Suppongo che oggigiorno siano perfetti per lo stesso tipo di roba di ArrayList – cioè assolutamente nulla.

AFAIK, verrebbe utilizzato in un test per falso, come quando l’operatore && entra in gioco. Ricorda, && cortocircuiti, quindi nell’espressione

 if ( mFalse && mTrue) { // ... something } 

mFalse.false() viene chiamato, e quando restituisce true l’espressione viene ridotta a una chiamata a ‘mFalse.true ()’ (che dovrebbe quindi restituire false , altrimenti le cose diventeranno strane).

Si noti che è necessario implementare l’operatore & affinché questa espressione possa essere compilata, poiché viene utilizzata se mFalse.false() restituisce false .

Viene visualizzato dall’articolo MSDN a cui è stato collegato il collegamento per consentire i tipi boolean nullable prima che il tipo Nullable (cioè int ?, bool ?, ecc.) Sia stato introdotto nella lingua in C # 2. Così si memorizzerebbe un valore interno che indica se il valore è vero o falso o nullo, cioè nell’esempio> 0 per true, <0 per false e == 0 per null, e quindi si otterrà la semantica nulla in stile SQL. Dovresti anche implementare un metodo .IsNull o una proprietà in modo che la nullità possa essere verificata esplicitamente.

Confrontando con SQL, immagina una tabella Table con 3 righe con valore Foo impostato su true, 3 righe con valore Foo impostato su false e 3 righe con valore Foo impostato su null.

 SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE 6 

Per contare tutte le righe dovresti fare quanto segue: –

 SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE OR Foo IS NULL 9 

Questa syntax ‘IS NULL’ avrebbe un codice equivoco nella tua class come. IsNull ().

LINQ rende ancora più chiaro il confronto con C #:

 int totalCount = (from s in MyTypeEnumerable where s || !s select s).Count(); 

Immaginando che MyTypeEnumberable abbia esattamente lo stesso contenuto del database, vale a dire 3 valori uguali a true, 3 valori uguali a false e 3 valori uguali a null. In questo caso totalCount valuterà a 6 in questo caso. Tuttavia, se abbiamo riscritto il codice come: –

 int totalCount = (from s in MyTypeEnumerable where s || !s || s.IsNull() select s).Count(); 

Quindi totalCount valuterà a 9.

L’esempio DBNull fornito nell’articolo MSDN collegato sull’operatore falso mostra una class nel BCL che presenta questo comportamento esatto.

In effetti la conclusione è che non dovresti usare questo a meno che non sei completamente sicuro di volere questo tipo di comportamento, è meglio usare semplicemente la syntax nullable molto più semplice !!

Aggiornamento: ho appena notato che è necessario sovrascrivere manualmente gli operatori logici!, || e && per farlo funzionare correttamente. Credo che il falso operatore si nutra di questi operatori logici, cioè indica la verità, la falsità o “altrimenti”. Come notato in un altro commento, x non funzionerà più; devi sovraccaricare! Stranezza!