Các toán tử cần biết trong Unity C#

Unity là một công cụ trò chơi thực hiện nhiều "heavy-lifting" cho các nhà phát triển về mặt chức năng và cho phép họ tập trung hoàn toàn vào quá trình phát triển. Nó sử dụng C# làm ngôn ngữ lập trình chính.

Giống như bất kỳ ngôn ngữ lập trình nào, C# bao gồm một mảng các hàm, kiểu, lớp, thư viện đặc biệt, v.v., nhưng nó cũng có một danh sách các ký hiệu đặc biệt (toán tử) mà mỗi ký hiệu có chức năng riêng. Trong bài đăng này, tôi sẽ liệt kê các ký hiệu đó và giải thích chức năng của chúng, để lần sau khi bạn mở một tập lệnh, bạn có thể nhanh chóng hiểu được ý nghĩa của từng phần.

Toán tử trong C# là một số ký hiệu đặc biệt thực hiện một số hành động trên toán hạng.

Trong C#, có 6 loại toán tử tích hợp: Toán tử số học, Toán tử so sánh, Toán tử logic Boolean, Toán tử bitwise và shift, Toán tử bằng nhau và Toán tử hỗn hợp. Biết tất cả chúng sẽ giúp bạn trở thành một lập trình viên giỏi hơn ngay lập tức.

1. Toán tử số học

Các toán tử sau đây thực hiện các phép tính số học với các toán hạng có kiểu số:

  • Các toán tử đơn ++ (tăng), -- (giảm), + (cộng) và - (trừ)
  • Các toán tử nhị phân * (nhân), / (chia), % (số dư), + (cộng) và - (trừ)

Toán tử tăng ++

Toán tử "add one" (hoặc ++) có nghĩa là += 1, nói cách khác, đây là cách nhanh chóng để thêm một số nguyên vào một giá trị số, mà không cần phải nhập thêm mã. Toán tử này có thể được thêm vào trước hoặc sau giá trị, điều này sẽ dẫn đến một hành vi khác:

//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

Toán tử giảm --

Toán tử "subtract one" ngược lại với ++ (-= 1), nghĩa là nó trừ một số nguyên khỏi một giá trị số. Nó cũng có thể được thêm vào trước hoặc sau một giá trị:

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

Toán tử một ngôi + và -

Toán tử + một ngôi trả về giá trị của toán hạng của nó và toán tử - một ngôi tính toán giá trị phủ định về mặt số của toán hạng của nó.

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

Toán tử nhân *

Toán tử nhân * tính toán tích nhân của các toán hạng của nó:

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

Toán tử phân chia /

Toán tử chia / chia toán hạng bên trái cho toán hạng bên phải.

Nếu một trong các toán hạng là số thập phân, toán hạng khác không thể là float hoặc double, vì float hoặc double không thể chuyển đổi ngầm định thành số thập phân. Bạn phải chuyển đổi rõ ràng toán hạng float hoặc double thành kiểu số thập phân.

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

Toán tử phần dư %

Toán tử phần dư % tính phần dư sau khi chia toán hạng bên trái cho toán hạng bên phải.

  • Đối với các toán hạng kiểu số nguyên, kết quả của a % b là giá trị được tạo ra bởi 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
  • Đối với các toán hạng thập phân, toán tử phần dư % tương đương với toán tử phần dư của kiểu 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

Toán tử cộng +

Toán tử cộng + tính tổng các toán hạng của nó. Bạn cũng có thể sử dụng toán tử + để nối chuỗi và kết hợp ủy nhiệm.

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

Toán tử trừ -

Toán tử trừ - trừ toán hạng bên phải của nó khỏi toán hạng bên trái. Bạn cũng có thể sử dụng toán tử - để xóa đại biểu.

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

2. Toán tử so sánh

Phép so sánh < (less than), > (greater than), <= (less than or equal), and >= (lớn hơn hoặc bằng), còn được gọi là toán tử quan hệ, so sánh các toán hạng của chúng. Các toán tử này được hỗ trợ bởi tất cả các kiểu số nguyên và số thực.

Toán tử nhỏ hơn <

Toán tử < trả về true nếu toán hạng bên trái nhỏ hơn toán hạng bên phải, trả về false nếu không.

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

Toán tử lớn hơn >

Toán tử > trả về true nếu toán hạng bên trái lớn hơn toán hạng bên phải, trả về false nếu không.

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

Toán tử nhỏ hơn hoặc bằng <=

Toán tử <= trả về true nếu toán hạng bên trái nhỏ hơn hoặc bằng toán hạng bên phải, trả về false nếu không.

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

Toán tử lớn hơn hoặc bằng >=

Toán tử >= trả về true nếu toán hạng bên trái lớn hơn hoặc bằng toán hạng bên phải, trả về false nếu không.

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. Toán tử logic Boolean

Các toán tử sau đây thực hiện các phép toán logic với toán hạng bool:

  • Toán tử ! (phủ định logic) đơn ngôi.
  • Các toán tử nhị phân & (AND logic), | (OR logic) và ^ (OR loại trừ logic). Các toán tử này luôn đánh giá cả hai toán hạng.
  • Toán tử nhị phân && (AND logic có điều kiện) và || (OR logic có điều kiện). Các toán tử này chỉ đánh giá toán hạng bên phải nếu cần thiết.

Toán tử phủ định logic!

Toán tử tiền tố đơn ! tính toán phủ định logic của toán hạng của nó. Nghĩa là, nó tạo ra true nếu toán hạng được đánh giá là false và false nếu toán hạng được đánh giá là true.

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

Toán tử logic AND &

Toán tử & tính toán AND logic của các toán hạng của nó. Kết quả của x & y là true nếu cả x và y đều đánh giá là true. Nếu không, kết quả là false.

Toán tử & đánh giá cả hai toán hạng ngay cả khi toán hạng bên trái đánh giá là false, do đó kết quả của phép toán là false bất kể giá trị của toán hạng bên phải.

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

Toán tử OR loại trừ logic ^

Toán tử ^ tính toán phép OR loại trừ logic, còn được gọi là phép XOR logic, của các toán hạng của nó. Kết quả của x ^ y là true nếu x được đánh giá là true và y được đánh giá là false, hoặc x được đánh giá là false và y được đánh giá là true. Nếu không, kết quả là false. Nghĩa là, đối với các toán hạng bool, toán tử ^ tính toán cùng một kết quả như toán tử bất đẳng thức !=.

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

Toán tử logic OR |

Toán tử | tính toán OR logic của các toán hạng của nó. Kết quả của x | y là đúng nếu x hoặc y được đánh giá là đúng, nếu không, kết quả là sai.

Toán tử | đánh giá cả hai toán hạng ngay cả khi toán hạng bên trái được đánh giá là đúng, do đó kết quả của phép toán là đúng bất kể giá trị của toán hạng bên phải.

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

Toán tử logic AND có điều kiện &&

Toán tử logic AND có điều kiện &&, còn được gọi là toán tử logic AND "short-circuiting", tính toán logic AND của các toán hạng của nó. Kết quả của x && y là true nếu cả x và y đều được đánh giá là true, nếu không, kết quả là false. Nếu x được đánh giá là false, y không được đánh giá.

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

Toán tử logic OR có điều kiện ||

Toán tử OR logic có điều kiện ||, còn được gọi là toán tử OR logic "short-circuiting", tính toán OR logic của các toán hạng của nó. Kết quả của x || y là đúng nếu x hoặc y được đánh giá là đúng. Nếu không, kết quả là sai. Nếu x được đánh giá là đúng, y không được đánh giá.

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. Toán tử bitwise và dịch chuyển

Các toán tử sau đây thực hiện các phép toán bitwise hoặc dịch chuyển với các toán hạng có kiểu số nguyên hoặc kiểu char:

  • Toán tử ~ đơn (bổ sung bit)
  • Toán tử dịch chuyển nhị phân << (left shift) and >> (dịch phải)
  • Các toán tử nhị phân & (AND logic), | (OR logic) và ^ (OR loại trừ logic)

Toán tử bổ sung bitwise ~

Toán tử ~ tạo ra phần bù bit của toán hạng của nó bằng cách đảo ngược từng bit.

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

Toán tử dịch trái <<

Toán tử << dịch chuyển toán hạng bên trái sang trái theo số bit được xác định bởi toán hạng bên phải của nó. Để biết thông tin về cách toán hạng bên phải xác định số lần dịch chuyển, hãy xem phần Số lần dịch chuyển của toán tử dịch chuyển.

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

Toán tử dịch chuyển phải >>

Toán tử >> dịch chuyển toán hạng bên trái sang phải theo số bit được xác định bởi toán hạng bên phải của nó.

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

Các vị trí bit trống bậc cao được thiết lập dựa trên loại toán hạng bên trái như sau:

  • Nếu toán hạng bên trái là kiểu int hoặc long, toán tử dịch chuyển phải thực hiện phép dịch chuyển số học: giá trị của bit quan trọng nhất (bit dấu) của toán hạng bên trái được truyền đến các vị trí bit trống bậc cao. Nghĩa là, các vị trí bit trống bậc cao được đặt thành 0 nếu toán hạng bên trái không âm và được đặt thành 1 nếu toán hạng âm.
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
  • Nếu toán hạng bên trái là kiểu uint hoặc ulong, toán tử dịch chuyển phải sẽ thực hiện phép dịch chuyển logic: các vị trí bit trống bậc cao luôn được đặt thành 0.
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

Toán tử logic AND &

Toán tử & tính toán phép toán logic AND từng bit của các toán hạng tích phân của nó.

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

Toán tử OR loại trừ logic ^

Toán tử ^ tính toán phép toán logic loại trừ bit, còn được gọi là phép toán logic XOR bit, của các toán hạng tích phân của nó.

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

Toán tử logic OR |

Toán tử | tính toán phép OR logic từng bit của các toán hạng tích phân của nó.

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

5. Toán tử đẳng thức

Các toán tử == (bằng nhau) và != (bất bằng nhau) kiểm tra xem các toán hạng của chúng có bằng nhau hay không.

Toán tử bằng nhau ==

Toán tử bằng == trả về true nếu các toán hạng của nó bằng nhau, trả về false nếu không.

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

Toán tử bất đẳng thức !=

Toán tử bất đẳng thức != trả về true nếu các toán hạng của nó không bằng nhau, trả về false nếu không. Đối với các toán hạng của các kiểu tích hợp, biểu thức x != y tạo ra cùng kết quả như biểu thức !(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. Các nhà điều hành khác nhau

Các toán tử hỗn hợp phổ biến là ?: để kiểm tra có điều kiện, :: để truy cập thành viên của không gian tên có bí danh và $ để nội suy chuỗi.

?: toán tử

Toán tử điều kiện ?:, còn được gọi là toán tử điều kiện ba ngôi, đánh giá một biểu thức Boolean và trả về kết quả của một trong hai biểu thức, tùy thuộc vào việc biểu thức Boolean được đánh giá là đúng hay sai, như ví dụ sau đây cho thấy:

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

:: toán tử

Sử dụng định danh bí danh không gian tên:: để truy cập thành viên của không gian tên có bí danh. Bạn chỉ có thể sử dụng định danh:: giữa hai định danh. Định danh bên trái có thể là bất kỳ bí danh nào sau đây:

  • Bí danh không gian tên được tạo bằng lệnh 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);
}
  • Một bí danh bên ngoài.
  • Biệt danh toàn cục, là biệt danh không gian tên toàn cục. Không gian tên toàn cục là không gian tên chứa các không gian tên và kiểu không được khai báo bên trong không gian tên được đặt tên. Khi được sử dụng với::, biệt danh toàn cục luôn tham chiếu đến không gian tên toàn cục, ngay cả khi có biệt danh không gian tên toàn cục do người dùng định nghĩa.
namespace MyCompany.MyProduct.System
{
    class Program
    {
        static void Main() => global::System.Console.WriteLine("Using global alias");
    }

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

toán tử $

Ký tự đặc biệt $ xác định một chuỗi ký tự là một chuỗi nội suy. Chuỗi nội suy là một chuỗi ký tự có thể chứa các biểu thức nội suy. Khi một chuỗi nội suy được giải quyết thành chuỗi kết quả, các mục có biểu thức nội suy được thay thế bằng các biểu diễn chuỗi của kết quả biểu thức.

Trong Interpolated Strings, ký hiệu đô la ($) được sử dụng để cho trình biên dịch C# biết rằng chuỗi theo sau nó sẽ được diễn giải là Interpolated String. Dấu ngoặc nhọn đóng gói các giá trị (của các biến) để đưa vào văn bản.

Để xác định một chuỗi ký tự là chuỗi nội suy, hãy thêm ký hiệu $ vào trước. Bạn không thể có bất kỳ khoảng trắng nào giữa $ và " để bắt đầu một chuỗi ký tự.

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.