7. Operátory

Množina operátorů v jazyce C# je až na pár výjimek identická s operátory v jiných programovacích jazycích, jako je třeba Java. Následující tabulka uvádí přehled operátorů seřazených dle priority.

Tabulka 4.1. tabulka priority operátorů

KategorieOperátory
primární(x) x.y f(x) a[x] x++ x-- new typeof sizeof checked unchecked
unární+ - ! ~ ++x --x (T)x
multiplikativní* / %
aditivní+ -
bitové posuny<< >>
relační< > <= >= is as
rovnost== !=
logické AND (bitové)&
logické XOR (bitové)^
logické OR (bitové)|
AND&&
OR||
podmíněný výraz? :
přiřazení= *= /= %= += -= <<= >>= &= ^= |=
  • typeof - slouží k reflexi. Vrátí instanci třídy System.Type.

    [ukázka kódu]
    Type t = typeof(Console);
    foreach(MemberInfo info in t.GetMembers()) Console.WriteLine(info);
  • sizeof - slouží k zjištění velikosti hodnotových typů. Tato operace je považována za nebezpečnou a proto musí být tento operátor umístěn v bloku unsafe.

    Definování bloku unsafe se explicitně zříkáme bezpečnostních kontrol prostředí .NET

    • Blok je definován pomocí klíčového slova unsafe a složenými závorkami.

    • Je nutné překladači povolit unsafe bloky (Project-Properties-Configuration Properties-Build-Allow Unsafe Code Blocks).

    [ukázka kódu]
    unsafe 
    {
      Console.WriteLine("Size of int: {0}",sizeof(int));
    }
  • Při porovnávání stringů pomocí operátoru == je porovnávána hodnota. Pokud chceme porovnat reference, musíme alespoň jeden řetězec přetypovat.

    [ukázka kódu]
    string a="hello";
    string b="hello";
    string c=String.Copy(a);
    Console.WriteLine(a==c); //True
    Console.WriteLine((object)a==(object)b); //True,same constant.
    Console.WriteLine((object)a==(object)c); //Flase

7.1. 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í.

[ukázka kódu]
if (someObject is SomeInterface) //vrátí true v případě, že someObject implementuje dané rozhraní
{ 
  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 as takto:

[ukázka kódu]
return someObject as SomeInterface;

7.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í:

[ukázka kódu]
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.

[ukázka kódu]
            string s = GetStringValue();
            Console.WriteLine(s ?? "Unspecified");
          

7.3. 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.

//this wont work
System.Console.WriteLine("doesnot work!"); 

//this will work
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).

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

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

[ukázka kódu]
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.

[ukázka kódu]
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);
  }
}

Následující tabulka ukazuje, které operátory lze přetížit.

Tabulka 4.2. Přetížitelné operátory

KategorieOperátory k přetížení
Unární operátory+ - ! ~ ++ --
Binární operátory+ - * / % & | ^ << >> != == < > <= >=
Logické konstantytrue false
Indexování[]
konverzní funkce(typ)

7.5. 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í:

  • implicitní - jsou prováděny aniž by uživatel musel cokoliv zadávat;

  • explicitní - uživatel misí zadat, že chce provést konverzi.

[ukázka kódu]
public static implicit operator type(object)
public static explicit operator type(object)

Použití demonstruje následující příklad:

[ukázka kódu]
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()
  {
    Test a="hello";     //implicit conversion
    string b=(string)a; //explicit conversion
  }
}