Operatorzy, których musisz znać w Unity C#

Unity jest silnikiem gry, który wykonuje wiele "heavy-lifting" dla deweloperów pod względem funkcjonalności i pozwala im skupić się wyłącznie na procesie rozwoju. Wykorzystuje C# jako główny język programowania.

Podobnie jak każdy język programowania, C# składa się z tablicy funkcji specjalnych, typów, klas, bibliotek itp., ale ma również listę symboli specjalnych (operatorów), z których każdy ma swoją własną funkcję. W tym poście wymienię te symbole i wyjaśnię, co one robią, tak aby następnym razem, gdy otworzysz skrypt, można było szybko zrozumieć, co oznacza każda część.

Operatory w języku C# to specjalne symbole wykonujące pewne działania na operandach.

W C# istnieje 6 typów wbudowanych operatorów: operatory arytmetyczne, operatory porównawcze, operatory logiczne Boole'a, operatory bitowe i przesunięcia, operatory równości i operatory różne. Znajomość wszystkich z nich sprawi, że od razu staniesz się lepszym programistą.

1. Operatory arytmetyczne

Poniżsi operatorzy wykonują operacje arytmetyczne na operandach typu liczbowego:

  • Operatory unarne ++ (inkrementacja), -- (dekrementacja), + (plus) i - (minus)
  • Operatory binarne * (mnożenie), / (dzielenie), % (reszta), + (dodawanie) i - (odejmowanie)

Operator inkrementacji ++

Operator "add one" (lub ++) oznacza += 1, innymi słowy, jest to szybki sposób na dodanie jednej liczby całkowitej do wartości liczbowej, bez konieczności wpisywania dodatkowego kodu. Operator ten może być dodany przed wartością lub po niej, co skutkowałoby innym zachowaniem:

//The result of x++ is the value of x before the operation, as the following example shows:
int i = 4;
Debug.Log(i);   // output: 4
Debug.Log(i++); // output: 4
Debug.Log(i);   // output: 5

//The result of ++x is the value of x after the operation, as the following example shows:
double a = 2.5;
Debug.Log(a);   // output: 2.5
Debug.Log(++a); // output: 3.5
Debug.Log(a);   // output: 3.5

Operator dekrementacji --

Operator "subtract one" jest przeciwieństwem ++ (-= 1), co oznacza, że ​​odejmuje jedną liczbę całkowitą od wartości liczbowej. Można go również dodać przed lub po wartości:

The result of x-- is the value of x before the operation, as the following example shows:
int i = 4;
Debug.Log(i);   // output: 4
Debug.Log(i--); // output: 4
Debug.Log(i);   // output: 3

The result of --x is the value of x after the operation, as the following example shows:
double a = 2.5;
Debug.Log(a);   // output: 2.5
Debug.Log(--a); // output: 1.5
Debug.Log(a);   // output: 1.5

Operatory unarne + i -

Operator unarny + zwraca wartość swojego operandu, a operator unarny - oblicza numeryczną negację swojego operandu.

Debug.Log(+5);     // output: 5

Debug.Log(-5);     // output: -5
Debug.Log(-(-5));  // output: 5

uint a = 6;
var b = -a;
Debug.Log(b);            // output: -6
Debug.Log(b.GetType());  // output: System.Int64

Debug.Log(-double.NaN);  // output: NaN

Operator mnożenia *

Operator mnożenia * oblicza iloczyn swoich operandów:

Debug.Log(6 * 3);         // output: 18
Debug.Log(1.5 * 3.5);     // output: 5.25
Debug.Log(0.1m * 24.4m);  // output: 2.44

Operator dywizji /

Operator dzielenia / dzieli swój lewy operand przez swój prawy operand.

Jeśli jeden z operandów jest dziesiętny, inny operand nie może być ani float, ani double, ponieważ ani float, ani double nie są domyślnie konwertowalne na decimal. Musisz jawnie przekonwertować operand float lub double na typ decimal.

Debug.Log(13 / 5);    // output: 2
Debug.Log(13 / 5.0);       // output: 2.6

int a = 13;
int b = 5;
Debug.Log((double)a / b);  // output: 2.6

Debug.Log(16.8f / 4.1f);   // output: 4.097561
Debug.Log(16.8d / 4.1d);   // output: 4.09756097560976
Debug.Log(16.8m / 4.1m);   // output: 4.0975609756097560975609756098

Operator reszty %

Operator reszty % oblicza resztę po podzieleniu operandu lewego przez operand prawy.

  • W przypadku operandów typu całkowitego, wynikiem a % b jest wartość wytworzona przez a - (a / b) * b
Debug.Log(5 % 4);   // output: 1
Debug.Log(5 % -4);  // output: 1
Debug.Log(-5 % 4);  // output: -1
Debug.Log(-5 % -4); // output: -1
  • W przypadku operandów dziesiętnych operator reszty % jest równoważny operatorowi reszty typu System.Decimal.
Debug.Log(-5.2f % 2.0f); // output: -1.2
Debug.Log(5.9 % 3.1);    // output: 2.8
Debug.Log(5.9m % 3.1m);  // output: 2.8

Operator dodawania +

Operator dodawania + oblicza sumę swoich operandów. Operatora + można również używać do łączenia ciągów znaków i łączenia delegatów.

Debug.Log(6 + 5);       // output: 11
Debug.Log(6 + 5.3);     // output: 11.3
Debug.Log(6.1m + 5.2m); // output: 11.3

Operator odejmowania -

Operator odejmowania - odejmuje prawy operand od lewego operandu. Możesz również użyć operatora - do usunięcia delegata.

Debug.Log(48 - 4);      // output: 44
Debug.Log(6 - 5.3);     // output: 0.7
Debug.Log(8.5m - 3.3m); // output: 5.2

2. Operatorzy porównania

Porównanie < (less than), > (greater than), <= (less than or equal), and >= (większe lub równe), znane również jako relacyjne, porównuje ich operandy. Operatory te są obsługiwane przez wszystkie typy liczbowe całkowite i zmiennoprzecinkowe.

Operator mniejszy niż <

Operator < zwraca wartość true, jeśli jego lewy operand jest mniejszy od prawego operandu, w przeciwnym wypadku zwraca wartość false.

Debug.Log(8.0 < 6.1);   // output: False
Debug.Log(6.1 < 6.1);   // output: False
Debug.Log(1.0 < 6.1);   // output: True

Debug.Log(double.NaN < 6.1);   // output: False
Debug.Log(double.NaN >= 6.1);  // output: False

Operator większy niż >

Operator > zwraca wartość true, jeśli jego lewy operand jest większy od prawego operandu, w przeciwnym wypadku zwraca wartość false.

Debug.Log(8.0 > 6.1);   // output: True
Debug.Log(6.1 > 6.1);   // output: False
Debug.Log(1.0 > 6.1);   // output: False

Debug.Log(double.NaN > 6.1);   // output: False
Debug.Log(double.NaN <= 6.1);  // output: False

Operator „mniejszy niż” lub „równy” <=

Operator <= zwraca wartość true, jeśli jego lewy operand jest mniejszy lub równy jego prawemu operandowi, w przeciwnym wypadku zwraca wartość false.

Debug.Log(8.0 <= 6.1);   // output: False
Debug.Log(6.1 <= 6.1);   // output: True
Debug.Log(1.0 <= 6.1);   // output: True

Debug.Log(double.NaN > 6.1);   // output: False
Debug.Log(double.NaN <= 6.1);  // output: False

Operator większy lub równy >=

Operator >= zwraca wartość true, jeśli jego lewy operand jest większy lub równy jego prawemu operandowi, w przeciwnym wypadku zwraca wartość false.

Debug.Log(8.0 >= 6.1);   // output: True
Debug.Log(6.1 >= 6.1);   // output: True
Debug.Log(1.0 >= 6.1);   // output: False

Debug.Log(double.NaN < 6.1);   // output: False
Debug.Log(double.NaN >= 6.1);  // output: False

3. Operatory logiczne Boole'a

Poniżsi operatorzy wykonują operacje logiczne na operandach boolowskich:

  • Operator unarny ! (negacja logiczna).
  • Operatory binarne & (logiczne AND), | (logiczne OR) i ^ (logiczne wyłączne OR). Te operatory zawsze oceniają oba operandy.
  • Operatory binarne && (warunkowe logiczne AND) i || (warunkowe logiczne OR). Operatory te oceniają prawy operand tylko wtedy, gdy jest to konieczne.

Operator negacji logicznej!

Operator jednoargumentowy prefiks ! oblicza logiczną negację swojego operandu. Oznacza to, że zwraca wartość true, jeśli operand jest oceniany jako false, i false, jeśli operand jest oceniany jako true.

bool passed = false;
Debug.Log(!passed);  // output: True
Debug.Log(!true);    // output: False

Operator logiczny AND &

Operator & oblicza logiczne AND swoich operandów. Wynik x & y jest prawdziwy, jeśli zarówno x, jak i y są oceniane jako prawda. W przeciwnym wypadku wynik jest fałszywy.

Operator & oblicza oba operandy, nawet jeśli lewy operand jest oceniany jako fałsz, więc wynik operacji jest fałszywy niezależnie od wartości prawego operandu.

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = false & SecondOperand();
Debug.Log(a);
// Output:
// Second operand is evaluated.
// False

bool b = true & SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

Operator logiczny wyłącznego OR ^

Operator ^ oblicza logiczne wyłączne OR, znane również jako logiczne XOR, swoich operandów. Wynik x ^ y jest prawdziwy, jeśli x jest prawdą, a y fałszem, lub x jest fałszem, a y prawdą. W przeciwnym wypadku wynik jest fałszywy. Oznacza to, że dla operandów boolowskich operator ^ oblicza ten sam wynik, co operator nierówności !=.

Debug.Log(true ^ true);    // output: False
Debug.Log(true ^ false);   // output: True
Debug.Log(false ^ true);   // output: True
Debug.Log(false ^ false);  // output: False

Operator logiczny OR |

Operator | oblicza logiczne OR swoich operandów. Wynik x | y jest prawdą, jeśli x lub y jest prawdą, w przeciwnym razie wynik jest fałszem.

Operator | oblicza oba operandy, nawet jeśli lewy operand jest prawdą, więc wynik operacji jest prawdą niezależnie od wartości prawego operandu.

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = true | SecondOperand();
Debug.Log(a);
// Output:
// Second operand is evaluated.
// True

bool b = false | SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

Warunkowy operator logiczny AND &&

Warunkowy operator logiczny AND &&, znany również jako operator logiczny AND "short-circuiting", oblicza logiczne AND swoich operandów. Wynik x && y jest prawdziwy, jeśli zarówno x, jak i y są oceniane jako prawda, w przeciwnym razie wynik jest fałszywy. Jeśli x jest oceniane jako fałsz, y nie jest oceniane.

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = false && SecondOperand();
Debug.Log(a);
// Output:
// False

bool b = true && SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

Operator warunkowy logiczny OR ||

Warunkowy operator logiczny OR ||, znany również jako operator logiczny OR "short-circuiting", oblicza logiczne OR swoich operandów. Wynik x || y jest prawdziwy, jeśli x lub y jest prawdziwe. W przeciwnym razie wynik jest fałszywy. Jeśli x jest prawdziwe, y nie jest oceniane.

bool SecondOperand()
{
    Debug.Log("Second operand is evaluated.");
    return true;
}

bool a = true || SecondOperand();
Debug.Log(a);
// Output:
// True

bool b = false || SecondOperand();
Debug.Log(b);
// Output:
// Second operand is evaluated.
// True

4. Operatorzy bitowi i przesunięciowi

Poniżsi operatorzy wykonują operacje bitowe lub przesunięcia z operandami typu liczb całkowitych lub typu char:

  • Operator unarny ~ (uzupełnienie bitowe)
  • Operatorzy przesunięcia binarnego << (left shift) and >> (przesunięcie w prawo)
  • Operatory binarne & (logiczne AND), | (logiczne OR) i ^ (logiczne wyłączne OR)

Operator uzupełnienia bitowego ~

Operator ~ generuje dopełnienie bitowe swojego operandu poprzez odwrócenie każdego bitu.

uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Debug.Log(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011

Operator przesunięcia w lewo <<

Operator << przesuwa swój lewy operand w lewo o liczbę bitów zdefiniowaną przez prawy operand. Aby uzyskać informacje o tym, jak prawy operand definiuje liczbę przesunięć, zobacz sekcję Liczba przesunięć operatorów przesunięć.

uint x = 0b_1100_1001_0000_0000_0000_0000_0001_0001;
Debug.Log($"Before: {Convert.ToString(x, toBase: 2)}");

uint y = x << 4;
Debug.Log($"After:  {Convert.ToString(y, toBase: 2)}");
// Output:
// Before: 11001001000000000000000000010001
// After:  10010000000000000000000100010000

Operator przesunięcia w prawo >>

Operator >> przesuwa swój lewy operand w prawo o liczbę bitów określoną przez swój prawy operand.

uint x = 0b_1001;
Debug.Log($"Before: {Convert.ToString(x, toBase: 2), 4}");

uint y = x >> 2;
Debug.Log($"After:  {Convert.ToString(y, toBase: 2), 4}");
// Output:
// Before: 1001
// After:    10

Pozycje pustych bitów wyższego rzędu są ustawiane na podstawie typu lewego operandu w następujący sposób:

  • Jeśli lewy operand jest typu int lub long, operator przesunięcia w prawo wykonuje przesunięcie arytmetyczne: wartość najbardziej znaczącego bitu (bitu znaku) lewego operandu jest propagowana do wyższych pozycji pustych bitów. Oznacza to, że wyższe pozycje pustych bitów są ustawiane na zero, jeśli lewy operand jest nieujemny i ustawiane na jeden, jeśli jest ujemny.
int a = int.MinValue;
Debug.Log($"Before: {Convert.ToString(a, toBase: 2)}");

int b = a >> 3;
Debug.Log($"After:  {Convert.ToString(b, toBase: 2)}");
// Output:
// Before: 10000000000000000000000000000000
// After:  11110000000000000000000000000000
  • Jeżeli lewy operand jest typu uint lub ulong, operator przesunięcia w prawo wykonuje przesunięcie logiczne: puste pozycje bitów wyższego rzędu są zawsze ustawiane na zero.
uint c = 0b_1000_0000_0000_0000_0000_0000_0000_0000;
Debug.Log($"Before: {Convert.ToString(c, toBase: 2), 32}");

uint d = c >> 3;
Debug.Log($"After:  {Convert.ToString(d, toBase: 2), 32}");
// Output:
// Before: 10000000000000000000000000000000
// After:     10000000000000000000000000000

Operator logiczny AND &

Operator & oblicza logiczny AND bitowy swoich operandów całkowitych.

uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 10011000

Operator logiczny wyłącznego OR ^

Operator ^ oblicza logiczną operację wyłączną OR (bitową operację logiczną XOR), znaną również jako logiczna operacja bitowa XOR, swoich operandów całkowitych.

uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 11100100

Operator logiczny OR |

Operator | oblicza bitową operację logiczną OR swoich operandów całkowitych.

uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Debug.Log(Convert.ToString(c, toBase: 2));
// Output:
// 10110001

5. Operatorzy równości

Operatory == (równość) i != (nierówność) sprawdzają, czy ich operandy są równe, czy nie.

Operator równości ==

Operator równości == zwraca wartość true, jeśli jego operandy są równe, lub false w przeciwnym wypadku.

int a = 1 + 2 + 3;
int b = 6;
Debug.Log(a == b);  // output: True

char c1 = 'a';
char c2 = 'A';
Debug.Log(c1 == c2);  // output: False
Debug.Log(c1 == char.ToLower(c2));  // output: True

Operator nierówności !=

Operator nierówności != zwraca true, jeśli jego operandy nie są równe, w przeciwnym wypadku false. W przypadku operandów typów wbudowanych wyrażenie x != y daje ten sam wynik, co wyrażenie !(x == y).

int a = 1 + 1 + 2 + 3;
int b = 6;
Debug.Log(a != b);  // output: True

string s1 = "Hello";
string s2 = "Hello";
Debug.Log(s1 != s2);  // output: False

object o1 = 2;
object o2 = 2;
Debug.Log(o1 != o2);  // output: True

6. Operatorzy różni

Do typowych operatorów różnych należą: ?: do sprawdzeń warunkowych, :: do dostępu do członka aliasowanej przestrzeni nazw i $ do interpolacji ciągu.

?: operator

Operator warunkowy ?:, znany również jako operator warunkowy trójargumentowy, ocenia wyrażenie boolowskie i zwraca wynik jednego z dwóch wyrażeń, w zależności od tego, czy wyrażenie boolowskie zwraca wartość prawda czy fałsz, jak pokazuje poniższy przykład:

bool condition = true;
Debug.Log(condition ? 1 : 2); // output: 1

:: operator

Użyj kwalifikatora aliasu przestrzeni nazw::, aby uzyskać dostęp do członka aliasowanej przestrzeni nazw. Kwalifikatora:: można używać tylko między dwoma identyfikatorami. Identyfikator po lewej stronie może być dowolnym z następujących aliasów:

  • Alias ​​przestrzeni nazw utworzony za pomocą dyrektywy using alias:
using forwinforms = System.Drawing;
using forwpf = System.Windows;

public class Converters
{
    public static forwpf::Point Convert(forwinforms::Point point) => new forwpf::Point(point.X, point.Y);
}
  • Alias ​​zewnętrzny.
  • Alias ​​globalny, który jest aliasem globalnej przestrzeni nazw. Globalna przestrzeń nazw to przestrzeń nazw zawierająca przestrzenie nazw i typy, które nie są zadeklarowane wewnątrz nazwanej przestrzeni nazw. Gdy jest używany z kwalifikatorem::, alias globalny zawsze odwołuje się do globalnej przestrzeni nazw, nawet jeśli istnieje zdefiniowany przez użytkownika alias globalnej przestrzeni nazw.
namespace MyCompany.MyProduct.System
{
    class Program
    {
        static void Main() => global::System.Console.WriteLine("Using global alias");
    }

    class Console
    {
        string Suggestion => "Consider renaming this class";
    }
}

Operator $

Znak specjalny $ identyfikuje literał ciągu jako interpolowany ciąg. Interpolowany ciąg to literał ciągu, który może zawierać wyrażenia interpolacji. Gdy interpolowany ciąg zostanie rozwiązany na ciąg wynikowy, elementy z wyrażeniami interpolacji są zastępowane przez reprezentacje ciągu wyników wyrażenia.

W przypadku ciągów interpolowanych znak dolara ($) jest używany do poinformowania kompilatora C#, że następujący po nim ciąg ma być interpretowany jako ciąg interpolowany. Nawiasy klamrowe zawierają wartości (zmiennych), które mają zostać uwzględnione w tekście.

Aby zidentyfikować literał ciągu jako interpolowany ciąg, należy dodać przed nim symbol $. Nie można umieszczać żadnej spacji między $ a ", które rozpoczynają literał ciągu.

string name = "John";
var date = DateTime.Now;
Debug.Log($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Output:
// Hello, John! Today is Wednesday, it's 19:40 now.