Chương 24: Các vấn đề khác về ngôn ngữ
Tác giả: Sưu tầm
Khái quát
Chương này đề cập đến các vần đề linh tinh về ngôn ngữ, bao gồm cách sử dụng hàm Main(), cách bộ tiền xử lý làm việc, và cách viết các giá trị nguyên mẫu.
Hàm Main
Một phiên bản đơn giản nhất của hàm Main() sẽ hoàn toàn tương tự các ví dụ khác:
using System;
class Test {
public static void Main() {
Console.WriteLine(“Hello, Universe!”);
}
}
Trả ra một tình trạng bằng số nguyên int
Nó sẽ thường là hữu ích để trả ra một tình trạng từ hàm Main(). Điều này được thực hiện bằng cách khai báo kiểu tra về của Main() là một số nguyên:
using System;
class Test {
public static int Main() {
Console.WriteLine(“Hello, Universe!”);
return(0);
}
}
Các tham số dòng lệnh
Các tham số dòng lệnh cho một ứng dụng có thể được truy xuất bằng cách khai báo hàm Main() với một mảng string như một tham số. Sau đó các tham số có thể được xử lý bằng cách chỉ mục mảng đó.
using System;
class Test {
public static void Main(string[] args) {
foreach (string arg in args)
Console.WriteLine(“Arg: {0}”, arg);
}
}
Nhiều hàm Main
Hàm Main thường hữu ích cho việc kiểm tra các mục đích để bao gồm một hàm static trong một lớp mà nó kiểm tra một lớp để chắc chắn nó làm mọi thứ đúng đắn. Trong C#, hàm kiểm tra static này có thể được viết như một hàm Main(), mà nó làm cho việc tự động các kiểm tra như vậy dễ dàng.
Nếu có một hàm Main() đơn lẻ được bắt gặp trong suốt thời gian biên dịch, trình biên dịch C# sẽ sử dụng nó. Nếu có nhiều hơn một hàm Main(), lớp chứa hàm Main() được mong muốn có thể được chỉ định trong dòng lệnh với tuỳ chọn /main:<classname>.
// error
using System;
class Complex {
public static int Main() {
// test code here
Console.WriteLine(“Console: Passed”);
return(0);
}
}
class Test {
public static void Main(string[] args) {
foreach (string arg in args)
Console.WriteLine(arg);
}
}
Biên tập tập tin này với /main:Complex sẽ sử dụng phiên bản kiểm tra của Main(), trong khi biên dịch với /main:Test sẽ sử dụng phiên bản thật sự của hàm Main(). Biên dịch nó mà không có cái nào cả sẽ dẫn đến một lỗi.
Tiền xử lý
Điều quan trong nhất để nhớ về bộ tiền xử lý C# là nó không tồn tại. Các đặc tính từ bộ xử lý C/C++ hoặc là vắng mặt hoàn toàn hoặc thể hiện trong một hình thức bị giới hạn. Đối với loại vắng mặt là include các tập tin và khả năng để thay đổi văn bản với #define. #ifdef và các chỉ thị kết hợp là còn và được sử dụng để điều khiển việc biên dịch mã.
Việc tống khứ phiên bản macro của #define cho phép lập trình viên hiểu rõ ràng hơn chương trình đang nói cái gì. Một tên không quen thuộc phải đến từ một trong những không gian tên, và không cần phải tìm kiếm trong include các tập tin để tìm nó.
Một trong những lý do lớn nhất cho thay đổi này là việc tống khứ tiền xử lý và #include cho phép một cấu trúc biên dịch đơn giản hoá, và do đó chúng ta có vài cải tiến đầy ấn tượng trong tốc độ biên dịch. Đồng thời, không cần phải viết một tập tin header độc lập và giữ nó đồng bộ với tập tin thi hành.
Khi tập tin nguồn C# được biên dịch, thứ tự biên dịch của các tập tin riêng biệt là không quan trọng, và nó là tương đương để chúng tất cả là trong một tập tin lớn. Không cần phải khai báo trước hay lo lắng về thứ tự các #includes.
Các dẫn hướng tiền xử lý
Các dẫn hướng tiền xử lý sau được hỗ trợ:
DẪN HƯỚNG |
MÔ TẢ |
#define định danh |
Định nghĩa một định danh. Chú ý là giá trị không thể được đặt cho nó; nó đơn thuần chỉ có thể định nghĩa. Các định danh cũng có thể được định nghĩa thông qua dòng lệnh. |
#undef định danh |
Bỏ định nghĩa một định danh. |
#if biểu thức |
Mã trong phần này được biên dịch nếu biểu thức là đúng |
#elif biểu thức |
Cấu trúc else-if. Nếu dẫn hướng trên không được thực hiện và biểu thức này là đúng, mã trong phần này sẽ được biên dịch. |
#else |
Nếu dẫn hướng trước không được thực hiện, mã trong phần này sẽ được biên dịch. |
#endif |
Đánh dấu kết thúc một phần. |
Đây là một ví dụ về cách chúng có thể được sử dụng:
#define DEBUGLOG
using System;
class Test {
public static void Main() {
#if DEBUGLOG
Console.WriteLine(“In Main Debug Enabled”);
#else
Console.WriteLine(“In Main No Debug”);
#endif
}
}
#define và #undef phải đứng trước bất kỳ “mã thực” nào trong tập tin, hay một lỗi sẽ xảy ra. Ví dụ trước không thể được viết như sau:
// error
using System;
class Test {
#define DEBUGLOG
public static void Main() {
#if DEBUGLOG
Console.WriteLine(“In Main Debug Enabled”);
#else
Console.WriteLine(“In Main No Debug”);
#endif
}
}
Các biểu thức tiền xử lý
Các toán tử sau có thể được sử dụng trong các biểu thức tiền xử lý:
TOÁN TỬ |
MÔ TẢ |
! ex |
Biểu thức là true nếu ex là false |
ex == value |
Biểu thức là true nếu ex bằng value |
ex != value |
Biểu thức là true nếu ex không bằng value |
ex1 && ex2 |
Biểu thức là true nếu cả hai ex1 và ex2 là true |
ex1 || ex2 |
Biểu thức là true nếu hoặc ex1 hoặc ex2 là true |
Dấu ngoặc có thể được sử dụng để nhóm các biểu thức:
#if !(DEBUGLOG && (TESTLOG || USERLOG))
Nếu TESTLOG hoặc USERLOG được định nghĩa và DEBUGLOG được định nghĩa, sau đó biểu thức trong ngoặc là đúng, mà nó sau đó được đảo ngược bởi “!”.
Các chức năng tiền xử lý khác
Ngoài các chức năng #if và #define, có một vài chức năng tiền xử lý khác có thể được sử dụng.
#warning và #error
#warning và #error cho phép các cảnh báo và các lỗi được báo cáo trong suốt tiến trình biên dịch. Tất cả các đoạn văn bản theo sau #warning và #error sẽ được xuất ra khi trình biên dịch đạt đến hàng đó.
Một mục của mã như sau có thể được thực hiện:
#warning Check algorthim with John
Điều này sẽ cho ra kết quả là một chuỗi “Check algorithm with John” được xuất ra khi dòng này được biên dịch.
#line
Với #line, lập trình viên có thể chỉ định một tên của tập tin nguồn và số dòng được báo cáo khi trình biên dịch bắt gặp lỗi. Cái này tiêu biểu được sử dụng với mã nguồn máy phát sinh, nên các dòng báo cáo có thể được đồng bộ với một cách đặt tên khác hay hệ thống đánh số.
Các vấn đề nguyên mẫu
Các vấn đề nguyên mẫi của ngôn ngữ giải quyết các thứ quan trọng ở cấp độ ký tự đơn: cách viết các hằng số học, các định danh, và các thực thể ngôn ngữ cấp độ thấp khác.
Các định danh
Một định danh là một tên được sử dụng cho một số thành phần chương trình, như một biến hay một hàm. Các định danh phải có một chữ cái hay một dấu gạch dưới là ký tự đầu tiên, và phần còn lại của định danh cũng có thể bao gồm các ký tự số học. Các ký tự Unicode có thể được chỉ định bằng cách sử dụng \udddd, phần dddd chỉ định giá trị hex của ký tự Unicode.
Khi sử dụng mã được viết trong một ngôn ngữ khác, một số tên có thể là từ khoá C#. Để viết một tên như vậy, một ký tự “at” (@) có thể được đặt trước tên, mà nó đơn thuần chỉ báo cho C# biết tên đó không phải là từ khoá, nhưng là một định danh.
Tương tự, sử dụng “@” để sử dụng các từ khoá như các định danh:
class Test {
public void @checked() {
}
}
Lớp này định nghĩa một hàm thành phần có tên checked.
Sử dụng đặc tính này để các định danh có thể cũng như các định danh dựng sẵn là không được đề nghị bởi vì sự nhầm lẫn mà nó có thể tạo ra.
Từ khoá
Các từ khoá là các từ được dành riêng mà không thể sử dụng như các định danh. Các từ khoá trong C# là:
Nguyên mẫu
abstract |
base |
bool |
break |
byte |
case |
catch |
char |
checked |
class |
const |
continue |
decimal |
default |
delegate |
do |
double |
else |
enum |
even |
explicit |
extern |
false |
finally |
fixed |
float |
for |
foreach |
goto |
if |
implicit |
in |
int |
interface |
internal |
is |
lock |
long |
namespace |
new |
null |
object |
operator |
out |
override |
params |
private |
protected |
public |
readonly |
ref |
return |
sbyte |
sealed |
short |
sizeof |
static |
string |
struct |
switch |
this |
throw |
true |
try |
typeof |
uint |
ulong |
unchecked |
unsafe |
ushort |
using |
virtual |
void |
while |
|
Các nguyên mẫu là cách các giá trị được viết cho các biến.
Boolean
Có hai nguyên mẫu Boolean: true và false.
Số nguyên
Các nguyên mẫu số nguyên được viết đơn giản bằng cách viết một giá trị số học. Các nguyên mẫu số nguyên là đủ nhỏ để vừa với kiểu dữ liệu in xem như các int; nếu chúng là quá lớn để vừa với in, chúng sẽ được tạo với các kiểu nhỏ nhất uint, long, hay ulong mà trong đó nguyên mẫu sẽ vừa.
Một số ví dụ nguyên mẫu số nguyên:
123
-15
Các nguyên mẫu số nguyên cũng có thể được viết ở dạng thập lục phân, bằng cách điền “0x” ở trước hằng:
0xFFFF
0x12AB
Số thực
Các nguyên mẫu số thực được sử dụng cho các kiểu float, double, và decimal. Các nguyên mẫu float có “f” hay “F” sau chúng; các nguyên mẫu double có “d” hay “D” sau chúng, và các nguyên mẫu decimal có “m” hay “M” sau chúng. Các nguyên mẫu số thực mà không có ký tự kiểu sẽ được diễn dịch như các nguyên mẫu double.
Ký hiệu số mũ có thể được sử dụng bằng cách chèn “e” theo sau bởi số mũ cho nguyên mẫu số thực.
Ví dụ:
1.345 // hằng double
-8.99e12F // hằng float
15.66m // hằng decimal
Ký tự
Các nguyên mẫu ký tự là một ký tự đơn nằm trong các dấu ngoặc đơn, như ‘x’. Các ký tự thoát sau được hỗ trợ:
KÝ TỰ THOÁT |
MÔ TẢ |
\’ |
Dấu ngoặc đơn |
\” |
Dấu ngoặc kép |
\\ |
Dấu sổ ngược |
\0 |
Null |
\a |
Alert |
\b |
Backspace |
\f |
Form feed |
\n |
Dòng mới |
\r |
Trở về đầu dòng |
\t |
Tab |
\v |
Tab dọc |
\xdddd |
Mỗi ký tự d là một số thập lục phân. |
Chuỗi
Các nguyên mẫu chuỗi được viết như một dãy các ký tự nằm trong các dấu ngoặc kép, như “Hello”. Tất cả các ký tự thoát cũng được hỗ trợ trong chuỗi.
Các chuỗi không thể kéo dài ra nhiều dòng, nhưng cùng một tác động có thể đạt được bằng cách nối chúng lại với nhau:
string s = “What is your favourite color?” +
“Blue. No, Red.”;
Khi mã này được biên dịch, một hằng chuỗi đơn sẽ được tạo, chứa hai chuỗi đã được nối với nhau.
Các chuỗi đúng nguyên văn
Các chuỗi đúng nguyên văn cho phép nhiều chuỗi được chỉ định đơn giản hơn.
Nếu một chuỗi chứa một ký tự gạch chéo ngược, như một tên tập tin, một chuỗi đúng nguyên văn có thể được sử dụng để hỗ trợ cho các chuỗi thoát. Thay vì viết như sau
string s = “c:\\Program Files\\Microsoft Office\\Office”;
có thể được viết như sau:
string s = @“c:\Program Files\Microsoft Office\Office”;
Cú pháp chuỗi đúng nguyên văn cũng hữu ích nếu mã được phát sinh bởi một chương trình và không có cách nào để ép buộc các nội dung của chuỗi. Tất cả các ký tự có thể được thể hiện như một chuỗi, dù bất kỳ sự kiện ký tự dấu ngoặc kép nào phải được nhân đôi:
string s = @“She said, ““Hello”””;
Ngoài ra, các chuỗi được viết với cú pháp chuỗi đúng nguyên văn có thể kéo dài nhiều dòng, và bất kỳ khoảng trắng nào (khoảng trống, tab, và ký tự dòng mới) cũng được giữ lại.
using System;
class Test {
public static void Main() {
string s = @”C: Hello, Miss?
O: What do you mean, ‘Miss’?
C: I’m Sorry, I have a cold. I wish to make a complaint.”;
Console.WriteLine(s);
}
}
Các chú thích
Các chú thích trong C# biểu thị bằng hai dấu gạch chéo cho chú thích đơn dòng, và /* và */ để biểu thị bắt đầu và kết thúc của một chú thích nhiều dòng.
// Đây là chú thích đơn dòng
/*
* Đây là chú thích đa dòng
*/
C# cũng hỗ trợ một kiểu chú thích đặc biệt được sử dụng để kết hợp tài liệu với mã; các chú thích này được mô tả trong phần tài liệu XML của Chương 31, “Xâu hơn với C#”.