2012-12-29 10 views
5

Gdy ten kawałek kodu, Equation(10, 20) jest wysyłany do konsoli:Wsparcie Boolean ale nadal mają wyświetlacz WriteLine użyciu ToString

public class Equation 
{ 
    public int a; 
    public int b; 

    public override string ToString() 
    { return "Equation(" + a + ", " + b + ")"; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine(new Equation() { a = 10, b = 20 }); 

     Console.ReadLine(); 
    } 
} 

Chciałbym wesprzeć Equation instancje wykorzystywany w teście if więc pozwolił na niejawna konwersja do Boolean:

public class Equation 
{ 
    public int a; 
    public int b; 

    public override string ToString() 
    { return "Equation(" + a + ", " + b + ")"; } 

    public static implicit operator Boolean(Equation eq) 
    { return eq.a == eq.b; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     if (new Equation() { a = 10, b = 10 }) 
      Console.WriteLine("equal"); 

     Console.WriteLine(new Equation() { a = 10, b = 20 }); 

     Console.ReadLine(); 
    } 
} 

jednak problem jest, teraz, gdy używam WriteLine na Equation, to get przeliczone t o a Boolean zamiast drukowania przy użyciu ToString.

Jak mogę zezwolić na niejawną konwersję na Boolean i nadal mam wyświetlanie WriteLine przy użyciu ToString?


aktualizacja

To pytanie jest inspirowana przez klasę Equation w SymbolicC++. Poniższy kod ilustruje, że Equation mogą być wyświetlane poprzez cout jak również wykorzystane w teście na if:

auto eq = x == y; 

cout << eq << endl; 

if (eq) 
    cout << "equal" << endl; 
else 
    cout << "not equal" << endl; 

Więc to jakoś możliwe w C++.

Odpowiedz

7

nie można zrobić z bool konwersji, ale można przeciążać operatory true i dla Equation. Oczywiście Equation nie będzie niejawnie zamienny do bool dłużej, ale nadal można go używać w if, while, do i for instrukcji i wyrażeń warunkowych (tj ?: operatora).

public class Equation 
{ 
    public int a; 
    public int b; 

    public override string ToString() 
    { return "Equation(" + a + ", " + b + ")"; } 

    public static bool operator true(Equation eq) 
    { 
     return eq.a == eq.b; 
    } 

    public static bool operator false(Equation eq) 
    { 
     return eq.a != eq.b; 
    }  
} 

ze swojego przykład:

if (new Equation() { a = 10, b = 10 }) 
    Console.WriteLine("equal"); // prints "equal" 

Console.WriteLine(new Equation() { a = 10, b = 20 }); // prints Equation(10, 20) 
+0

Wow, zabiłeś to Mike. Dzięki! – dharmatech

+0

Podczas gdy "Równania" działają w wyliczeniach, które wymieniłeś, wygląda na to, że nie działają z operatorami '||' i '&&'. Pomyślałem, że wspomnę o tym ludziom, którzy rozważają tę opcję. – dharmatech

+0

@dharmatech Jak już powiedziałem, nie można go już przekształcić w 'Boolean'. Moglibyśmy przeciążyć także operatory '&' i '|', ale byłoby to ograniczone, ponieważ nadal nie moglibyśmy zrobić czegoś takiego jak 'eq && true'. Zgadzam się z komentarzem Jona, że ​​tego typu rzeczy są trochę zbyt sprytne i mogą być mylące zarówno dla konsumentów twojego kodu, jak i przyszłych opiekunów. –

12

Nie można, o ile mogę powiedzieć. Możesz także również zapewnić konwersję na ciąg ... ale to sprawi, że wywołanie będzie niejednoznaczne między WriteLine(string) i WriteLine( bool`).

Osobiście będę zdecydowanie polecam, aby porzucić niejawną konwersję na Boolean. Konwersje niejawne prawie zawsze stanowią zły pomysł. Sprawiają, że kod jest znacznie bardziej zagmatwany, jak również prowadzi do niezamierzonych zmian przeciążenia, jak już znalazłeś.

(ja również zmienić swój styl usztywniania ale to już zupełnie inna sprawa.)

+2

rzeczywiście można) – SergeyS

+0

Jon, sprawdź odpowiedzi przez 'Mike z'. To prawie robi to, czego szukam. Czy widzisz jakieś wady tego podejścia? – dharmatech

+11

@dharmatech: Cóż, nie odpowiada na pytanie, jak je wstawiasz, czyli na zachowanie niejawnej konwersji na 'bool'. Osobiście nie przeciążyłbym również operatorów "prawdziwych" i "fałszywych" - zachowałbym to bardziej wyraźnie. Uważam, że próbowanie bycia "uroczym" w takich operatorach zwykle prowadzi do kodu trudniejszego do utrzymania. YMMV oczywiście - ale byłbym bardzo ostrożny. –

8

To dlatego Console.WriteLine (bool) przeciążenie nazywa zamiast Console.WriteLine (Object). Można jawnie oddanych do obiektu i wymagała przeciążenie będzie nazwane:

Console.WriteLine((object)(new Equation() { a = 10, b = 20 })); 

lub alternatywnie expliciltly zadzwonić .ToString():

Console.WriteLine((new Equation() { a = 10, b = 20 }).ToString());