2015-08-14 19 views
7

seguito this very interesting issue che è stato originato da this domanda -&& sovraccarico operatore e assegnazioni in C# - Chiarificazione?

voglio prendere 1 passi indietro si prega di (tolto l'ambiente dinamico):

Guardando questo codice: (a variant of this one)

void Main() 
{ 
    int a; 
    int b = 100; 
    Console.WriteLine(X.M(1, out a)); 

} 

public class X 
{ 
    public int H=0; 

    public static X M(int x, out int y) 
    { 
     Console.WriteLine("x = "+x); 
     y = x; 
     return new X(x); 
    } 

    public X(){} 

    public X(int h) 
    { 
     H=h; 
    } 

    public static bool operator false(X x)  {Console.WriteLine("in false operator for "+ x.H); return true; } 
    public static bool operator true(X x)  {Console.WriteLine("in true operator for "+ x.H); return true; } 
    public static X operator &(X a, X b)  {Console.WriteLine("in & operator for "+ a.H+","+b.H); return new X(); } 
    public static implicit operator bool (X x) {Console.WriteLine("in bool operator for "+ x.H);return true; } 
} 

Il risultato è:

.210

Questo è capito:

  • Il x = 1 è dal metodo stesso (utilizzando Console.Writeline)
  • in bool operator for 1 da parte dell'operatore implicita da X a Bool (così - Console.WriteLine tratta l'intera espressione come Console.Writeline(bool))
  • L'ultimo "Vero" è dal "return true" nello operator bool (X x)

OK - Così cambiamo

Console.WriteLine(X.M(1, out a)); 

a

Console.WriteLine(X.M(1, out a) && X.M(2, out b)); 

ora - il risultato è:

x = 1 
in false operator for 1 
in bool operator for 1 
True 

2 domande:

  1. Perché viene eseguito questo in false operator for 1? Non vedo alcun motivo per cui false sia presente qui.

  2. Posso capire perché la parte destra in X.M(1, out a) && X.M(2, out b) non verrà eseguita SOLO se la parte sinistra è false - ma di nuovo non vedo come la parte sinistra possa essere falsa. Lo fa tornare true (secondo il mio primo codice)

NB

ho letto molte volte le risposte da posta:

Jon ha detto:

Il secondo & & è un normale & & tra due espressioni bool - perché Nop r eturns bool, e non c'è l'operatore & (X, bool) ... ma c'è una conversione da X a bool.

Quindi è più simile a:

bool primo = X.M (1, out a) & & X.M (2, fuori b);
se (prima & & Nop (a, b))

Ora prima è vero anche se solo il primo operando di & & è stata valutata ... quindi b in realtà non è stato assegnato.

Ancora non capisco: "prima è true (????), anche se solo il primo operando di & & è stato valutato"

+0

Se l'operatore 'false()' restituisce 'true', significa che l'operazione restituisce' false' ("è x falso? Sì è (restituisce true;)")! Non è un 'operatore bool()'. – xanatos

+0

L'operatore 'false()' è chiamato a cortocircuitare '&&' ... Potrebbero aver chiamato l'operatore' true() ', ma per esempio la definizione di' && 'in [msdn] (https://msdn.microsoft.com/en-us/library/2a723cdk.aspx): * tranne che ** se x è falso **, y non viene valutato * – xanatos

+0

Vedere http://stackoverflow.com/a/5203515/613130 : * && è definito come un operatore di cortocircuito; ** se il primo operando valuta falso **, viene richiesto di cortocircuitare e non valutare il lato destro. * – xanatos

risposta

5

In primo luogo, non dimenticate che questo è un codice deliberatamente bizzarro, usato per trovare un caso d'angolo. Se trovi un tipo che si comporta in questo modo in un programma originale, trova l'autore e parla tranquillamente con loro.

Ancora non capisco: "prima è vera (????), anche se solo il primo operando di & & è stato valutato"

Sì, a causa del modo in cui la && l'operando viene gestito nel caso in cui gli operandi non siano bool. E 'riportato alla sezione 7.12.2 del C# spec:

L'operazione x && y viene valutata come T.false(x) ? x : T.&(x, y) dove T.false(x) è un'invocazione dello operator false dichiarata in T, e T.&(x, y) è un'invocazione dell'operatore selezionato nel &. In altre parole, x viene prima valutato e operator 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. In caso contrario, viene valutato y e il valore selezionato operator & viene richiamato sul valore precedentemente calcolato per x e il valore calcolato per y per produrre il risultato dell'operazione.

Così, al fine di:

  • X.M(1, out a) viene invocato, per ottenere un risultato - lo chiamano op1 per il momento
  • successivo X.false(op1) viene richiamato, e restituisce true
  • Poi dal sopra , il risultato dell'espressione X.M(1, out a) && X.M(2, out b) è op1
  • Successivamente, il valore della conversione da op1 a bool viene richiamato e restituisce true. Ciò è dovuto alla risoluzione di sovraccarico per Console.WriteLine.

Per rispondere alla tua confusione specifica:

ma ancora una volta non vedo come la parte sinistra può essere false.It fa ritorno vero (secondo il mio primo codice)

Restituisce un valore alquanto contraddittorio: è false in quanto l'operatore restituisce true, ma è true in quanto la conversione in bool restituisce true. Una volta compreso che è il valore restituito dall'operatore false che determina se valutare o meno il secondo operando di &&, dovrebbe essere tutto chiaro.

+0

Ma perché invoca il '' 'operatore bool'''? Mentre interpreto le specifiche, il risultato dell'operazione '' '&&' '' dovrebbe essere solo il risultato della chiamata '' operatore & '' '. – erikkallen

+1

@erikkallen: Dipende dal contesto :) Nel contesto della chiamata 'Console.WriteLine', è perché c'è un sovraccarico che accetta' bool', e questo è più specifico del sovraccarico che accetta 'object'. Nel contesto originale del programma di Neal Gafter, era perché il risultato sarebbe stato usato come primo operando in * un'altra espressione * '&&', dove l'espressione della mano destra era di tipo 'bool'. –

+0

Grazie per la spiegazione. Devo dire che sono piuttosto sorpreso dal fatto che userà operatori impliciti per individuare sovraccarichi più specifici. – erikkallen