csharp.aspone.cz csharp.aspone.cz

Operátory

Základní
OperátorVýznam
.přístup k členu/metodě objektu
->ukazatel na člena struktury
&reference
*dereference
f(x)volání metody
c++;následný inkrement
c--;následný dekrement
(typ)přetypování
[]indexace (pole)
newvytvoření instance
sizeof(int)velikost struktury
checked {byte c = (byte) d;}kontrola přeteční zapnuta
unchecked {byte c = (byte) d;}kontrola přeteční vypnuta
Matematické
OperátorVýznam
a + bsčítání
a - bodčítání
a * bnásobení
a / bdělení
a % bmodulo
Unární
OperátorVýznam
int* c = d; hodnota adresy
int* c = &d; adresa hodnoty
++c; předcházející (prefix) inkrement
--c; předcházející (prefix) dekrement
Relační
OperátorVýznam
a < b menší než
a > b větší než
a <= b menší nebo rovno
a >= b větší nebo rovno
a == b rovná se
a != b nerovná se
int c = (d<10) ? 5:15 zkrácená podmínka
Logické
OperátorVýznam
&&logické AND
||logické OR
!logická negace
Bitové
OperátorVýznam
&bitové AND
|bitové OR
^bitové XOR
<<bitový posun vlevo
>>bitový posun vpravo
~bitová negace
Přiřazení
OperátorVýznam
= += -= *= /= %= |= ^= <<= >>=

Zkrácený zápis operátorů

Zkrácený zápisOdpovídá
x++, ++xx = x + 1
x--, --x x = x - 1
x += yx = x + y
x -= yx = x - y
x *= yx = x * y
x /= yx = x / y
x %= yx = x % y
x >>= yx = x >> y
x <<= yx = x << y
x &= yx = x & y
x |= yx = x | y
x ^= yx = x ^ y

Nahoře jsou uvedeny dva příklady inkrementačních a dekrementačních operátorů ++ a --. Když je ++= nebo --= jedná se o prefixový výraz a když =++ nebo =-- jde o postfixový výraz.

Prefix - zvýší/sníží hodnotu výrazu před vyhodnocením výrazu. Nejprve je zvýšena/snížena hodnota proměnné a teprve poté je použíta v příslušném výrazu

Postfix - zvýší/sníží hodnotu výrazu po vyhodnocení výrazu. Nejprve je vyhodnocení výrazu - výraz je vyhodnocen s původní hodnotou proměnné a teprve poté je zvýšen/snížen.

Priorita operátorů

Priorita operátorů nám určuje, jak se budou operátory vyhodnocovat, když budou v jistém pořadí. Seznam začíná s operátory s nejvyšší prioritou.

SkupinaOperátory
Unární () . [] x++ x-- new typeof sizeof checked unchecked + ! - ~ ++x --x a přetypování
Násobení,dělení * / %
Sčítání, odčítání+ -
Bitové operátory posunu<< >>
Porovnání== !=
Bitová konjukce (AND)&
Bitová nonekvivalence (XOR)^
Bitová disjunkce (OR) |
Logická konjunkce (AND)&&
Logická disjunkce (OR)||
Ternární operátor? :
Přiřazení= += -= *= /= %= &= |= ^= <<= >>= >>>=

Aritmetické výrazy

Zde jsou použity aritmetické výrazy, prefixi a postfixi, schválně si zkuste jak budou vycházet výsledky jen tak a pak program přeložte. Je to dobré k uvědomění si priority, asociativity a vyhodnocování prefixu a postfixu.

using System;

class vyrazy
{
        static void Main()
        {
                int a, b, c, d, e;

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", a++ / ++c * --e); 

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", --b * c++ - a); 

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", -b - --c);

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", ++a - --e); 

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", e / --a * b++ / c++);

                a = 2; b = 2; c = 1; d = 0; e = 4;
                Console.WriteLine("{0}", a %= b = d = 1 + e / 2);
        }
}

Operátor ??

C# 2.0 poskytuje nový operátor ?? nazvaný null splývající operátor (null coalescing operator) . Výsledek výrazu A ?? B je A, pokud je A non-nullable typu. Jinak je výsledek B. Pokud A obsahuje hodnotu null, tak B poskytne hodnotu k použití. Výraz A ?? B tedy vrací non-nullable hodnotu a poskytne vhodné implicitní přetypování:

        int? x = GetNullableInt();
        int? y = GetNullableInt();
        int? z = x ?? y;
        int i = z ?? -1;

Typ výrazu x ?? y je int?, ale výraz z ?? -1 je typu int. Operátor splývající null také funguje pro odkazové typy. Ukázka příkladu, kde program vypíše buď proměnnou s anebo, pokud je snull, vypíše Unspecified.

        string s = GetStringValue();
        Console.WriteLine(s ?? "Unspecified"); 

Operátory is a as

Pomocí operátoru is jsem schopni zjistit, zda je daný prvek instancí dané třídy, případně implementuje-li dané rozhraní.

        if (someObject is SomeInterface) { 
                return someObject;
        } 
        else {
                return null;
        }

Operátor as provádí přetypování na daný typ. Pokud přetypování není možné, vrací null. Předvedený příklad by tedy šlo implementovat pomocí operátoru asi takto:

        return someObject as SomeInterface;

Operátor ::

Ve verzi 2.0 v jazyce C# přibyl nový operátor ::. Pro minimalizaci nebezpečí záměny jmen je doporučováno používat plně kvalifikovaná jména (např. System.Console.WriteLine místo Console.WriteLine). Pokud se však v kódu vyskytuje například následující deklarace, použití plně kvalifikovaného jména nestačí.

        int System, Console;
 

Tato deklarace efektivně znemožní vypisování čehokoliv na obrazovku. Nyní však můžete použít operátor :: (dvě dvojtečky) pro přístup ke globálním jménům.

        // toto nepůjde
        System.Console.WriteLine("doesnot work!"); 

        // toto ano
        global::System.Console.WriteLine("works!");

Nutno upozornit, že funkce operátoru :: je zde odlišná od jazyka C++. Je to binární operátor, na levé straně uvádíme obvykle slovo global reprezentující globální prostor jmen, můžeme také uvést zástupné jméno prostoru jmen. V druhém případě má operátor :: podobný význam jako operátor . (tečka), avšak omezuje hodnotu na levé straně pouze na zástupná jména (namespace aliases).

Přetěžování operátorů

Jazyk C# umožňuje přetěžování operátorů.

        public static returnType operator op (object1 [,object2]) {...}
 

Definice operátoru je vždy veřejná a statická. Následuje návratový typ. Obecně to může být libovolný typ. Klíčové slovo operátor určuje, že chceme přetížit operátor op. Přetěžujeme-li unární operátor definujeme jediný parametr. Pro operátory binární budou parametry dva. Na tyto parametry nejsou kladeny žádné omezení. Je vhodné, aby první parametr byl stejného typu jako třída, jejíž operátor přetěžujeme.

        class Test
        {
                protected string text;
                
                public Test(string text) 
                {
                        this.text = text;
                }
        
                public string Text
                {
                        get
                        { 
                                return this.text;
                        }
            
                        set
                        {
                                this.text = value;
                        }
                }
  
                public static Test operator + (Test t1,Test t2) 
                {
                        return new Test(t1.Text+","+t2.Text);
                }
        }
    
        class RunApp
        {
                public static void Main()
                {
                        Test a = new Test("A");
                    Test b = new Test("B");
                    Test c = a + b;
                    Console.WriteLine(c.Text);
                    Console.WriteLine((a+b).Text);
                    a + =b;
                    Console.WriteLine(a.Text);
                }
        }

Logicky si můžeme i odvodit a musíme vědět, že nelzou přetížit všechny operátory. Vše najdeme v patřičné dokumentaci, nebo kdekoliv jinde.

Uživatelsky definované konverze

Slouží ke konverzi třídy nebo struktury do jiné třídy, struktury nebo základního typu. Typ, pro kterou je konverze definovaná, se musí objevit buď v parametru nebo musí konverze tento typ vracet a opět (podobně jako u operátorů) musí být definice veřejná a statická. Jsou dva druhy uživatelsky definovaných konverzí:

1) implicitní - jsou prováděny aniž by uživatel musel cokoliv zadávat.
2) explicitní - uživatel misí zadat, že chce provést konverzi.

            public static implicit operator type(object);
            public static explicit operator type(object);
    

A jdeme si to ukázat na příkladě:

        class Test
        {
                protected string text;
            
                public string Text
                {
                        get
                        {
                                return this.text;
                        }
                        
                        set
                        {
                                this.text = value;
                        }
                }
  
                public static implicit operator Test(string a) 
                {
                        Test t = new Test();
                        t.Text = a;
                        return t;
                }

                public static explicit operator string(Test a) 
                {
                        return a.Text;
                }
        }

        class RunApp
        {
                public static void Main()
                {
                        // Implicitní konverze.
                        Test a = "hello"; 
                        // Explicitní konverze.
                        string b = (string)a;
                }
        }