True és false operátorok a C#-ban

Éppen egy C# 2008 és .NET 3.5 Platform című könyvet lektorálom és abban olvastam, hogy a true és false nem csak literálként szerepelhet, hanem operátor is lehet a C#-ban. Első olvasatra azt hittem, hogy csak gépelési hiba, de aztán megint felhozta a könyv a témát. Na nekem sem kellett több kipróbáltam, hogy mi is ez, mert néhány kérdés felmerült bennem:

  • Hogyan lehet ezt használni?
  • Mi előnyöm származik abból, ha ezt túlterhelem. Egyáltalán lehet valami értelmesre használni?
  • Van valami köze a && és || operatorokhoz?

A true operátort egyszerűen kitalálhatjuk, hogy akkor hívódik, ha létrehozok egy saját osztály, és ennek egy példányát teszem például egy if-be. Ekkor a saját osztályon meghívódik a true operátor ami valójában annyit tesz, hogy egy bool értéket ad vissza az egyedi típusból.

Készítettem egy saját osztályt ThreeStateBool névvel, melynek kódja az alábbi:

public class ThreeStateBool
{
    // A három használt érték
    public static readonly ThreeStateBool NotDefined = new ThreeStateBool( 0 );
    public static readonly ThreeStateBool False = new ThreeStateBool( -1 );
    public static readonly ThreeStateBool True = new ThreeStateBool( 1 );

    // Belső értéket itt tárolom
    private sbyte value;

    // privát konstruktor
    private ThreeStateBool( int value)
    {
        this.value = (sbyte) value;
    }

    // true operátor
    public static bool operator true( ThreeStateBool x )
    {
        Console.WriteLine( "true operátor hívása..." );
// szándékosan false! return false; } // false operátor public static bool operator false( ThreeStateBool x ) { Console.WriteLine( "false operator hívása..." );
// szándékosan false!
return false; } }

Mint látható a kódban túlterheltem a true, false, operátorokat. Ekkor ha lefuttatom az alábbi pédakódot, látható, hogy valóban meghívódik a true operátor, amikor az elágazást megpróbálja kiértékelni. Íme a teszthez használt kód:

class Program
{
    static void Main( string[] args )
    {
        if( ThreeStateBool.True )
            Console.WriteLine( "Eredmény: True" );
        else
            Console.WriteLine( "Eredmény: False" );
    }
}

Szuper, már sikerült meghívni a true operátort. Azonban hogyan tudom meghívni a false operátor?? A probléma, hogy egyszerű if-ben ezt nem tudjuk megtenni. Ahhoz, hogy le tudjuk futtatni a false operátor kódját, végig kell gondolni, hogy a && illetve || operátorok hogyan működnek. Mivel ezek az operátorok csak addig értékelik ki a kifejezést, amíg egyértelmű választ nem tudnak adni a teljes kifejezésre. Ez azt jelenti, hogy az && addig értékeli ki az elemeket, amíg nem talál egy false értéket, míg a || operátor addig értékeli ki a kifejezést, amíg nem talál egy true értéket.

A gond csupán az, hogy ezeket az operátorokat nem tudjuk túlterhelni. Vagy egy kis trükkel mégis?

Módosítsuk a teszt kódot úgy, hogy hívjuk meg a ThreeStateBool-ra az && illetve || operátort a tesztkódban:

class Program
{
    static void Main( string[] args )
    {
        Console.WriteLine( "False && NotDefined" );
        if( ThreeStateBool.False && ThreeStateBool.NotDefined )
            Console.WriteLine( "Eredmény: True" );
        else
            Console.WriteLine( "Eredmény: False" );

        Console.WriteLine( "\nTrue és NotDefined" );
        if( ThreeStateBool.True || ThreeStateBool.NotDefined )
            Console.WriteLine( "Eredmény: True" );
        else
            Console.WriteLine( "Eredmény: False" );
    }
}

Sajnálatos módon ekkor nem fog fordulni a kódunk, mert nincs túlterhelve a && illetve || operátor a ThreestateBool osztályra. Viszont ha ezt megpróbáljuk túlterhelni, akkor azt fogjuk tapasztalni, hogy ezeket az operátorokat nem lehet túlterhelni. Akkor mit lehet tenni.

A megoldás lényege az, hogy a & illetve |operátorok és a true illetve false operátor segítéségével oldja meg a C# a && illetve ||operátorokat. Tehát ha túlterheljük a & és | operátorokat is, akkor fogjuk tudni használni a && és || operátorokat is.

Egészítsük ki a ThreeStateBool osztályunkat a két operátor túlterhelésével:

// ÉS operátor. 
public static ThreeStateBool operator &( ThreeStateBool x, ThreeStateBool y )
{
    Console.WriteLine( "& operátor hívása..." );
    return new ThreeStateBool( x.value < y.value ? x.value : y.value );
}

// VAGY orperátor. 
public static ThreeStateBool operator |( ThreeStateBool x, ThreeStateBool y )
{
    Console.WriteLine( "| operátor hívása..." );
    return new ThreeStateBool( x.value > y.value ? x.value : y.value );
}

Ekkor már lefordul a kód. Futtassuk is le és nézzük meg, hogy mi történik.

image

Érdekes dolog történt. Az első kifejezésnél kiértékelődött a && illetve a 2. operandus is, pedig nem lett volna szabad kiértékelődni, hiszen az első elem már hamis, azaz az egész kifejezés csak hamis lehet. Vagy mégsem? Az && operátor a false operátor segítségével dönti el, hogy a TreeStateBool.False milyen logikai érétket adjon vissza. Jelen esetben mindig false-t kapunk vissza, ami miatt az && kifejezésnek tovább kell futnia.

A || operátor teljesen hasonlóan működik, csak ott a true operátor kerül mindig meghívásra. Mivel azonban a fenti implementációban az is mindig false-t ad vissza, ezért a kifejezés kirtékelése nem tud befejeződni korábban, így minden elemét kiértékeli.

Tehát a true, false, & és | operátorok túlterhelésével befolyásolni tudjuk, hogy a && illetve || operátorok hogyan működjenek. A false a && operátor “rövidített útját” határozza meg, míg a true opertárot a || operátorét. (Amikor a true operátor true-t ad vissza, akkor a || nem értékeli ki tovább a kifejezést, amikor pedig a false operátor ad vissza true-t akkor az && kiértékelése szakad meg.

Hogy ennek hol van értelme azt mindenki döntse el saját maga.



Gincsai Gábor

Gincsai Gábor Műszaki informatikusként végeztem a BME-n és jelenleg a BME Automatizálási és Alkalmazott Informatikai Tanszékén programozás és webes fejlesztés oktatásával foglalkozom. Jópár éve tartok különböző előadásokat Microsoftos technológiákról főként az ASP.NET-ről. Az MSDN Kompetencia Központon belül a Portál Technológiák Csoport szakembere vagyok, illetve 2008 óta ASP.NET MVP.

2009.02.13. 12:01:55 | Permalink | Hozzászólások: 0 | Tárgyszavak:


  • ASP.NET Menu és a kifele mutató linkek

    Dávid Zoltán ASP.NET-ben a Menu vezérlő szuperül használható a weboldal menüjének megjelenítésére. Adatait tudja például SiteMap állományokból venni, iránya mélysége beállítható. Sőt ha bekapcsolod a securityTrimminget, akkor nem mutatja meg azokat a menüpontokat, melyek mögött található oldalakat nincs jogod megnézni. A pontos működési mechanizmusáról már volt szó korábban is. Tovább »
  • Böngészőfelbontás detektálás szerveroldalon

    Dávid Zoltán Van egy alkalmazásom néhány előre definiált CSS-sel. Szerveroldalon OnPreRender-ben állítom be, hogy melyiket használja ezek közül a böngésző. Valahogy így. Tovább »


Írja meg Ön is véleményét!


Hozzászólásokat csak regisztrált, bejelentkezett felhasználóktól tudunk elfogadni!

Hozzászólások