Menu

Chuyển string sang int, ép kiểu trong C#: Parse, TryParse, Convert

Cách chuyển một chuỗi sang int trong C# bằng int.Parse, int.TryParse và Convert.ToInt32, cách ép kiểu ngầm định và tường minh hoạt động, vì sao ép một double thì phần thập phân bị cắt bỏ, toán tử as và is, và vì sao "1.5" có thể được parse thành 15.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

C# không bao giờ tự chuyển đổi giữa các kiểu không liên quan. Một chuỗi chứa chữ số vẫn là chuỗi, và một double không lặng lẽ biến thành int. Bạn phải chuyển đổi tường minh, và công cụ cần dùng tùy vào thứ bạn đang chuyển: văn bản sang số (parse), kiểu số này sang kiểu số khác (ép kiểu, casting), hay một đối tượng sang một kiểu cụ thể hơn (as, is).

Chuyển string sang int: Parse, TryParse và Convert

Có ba cách chuẩn để biến văn bản thành một int:

Đầu ra:

2500
TryParse ok: 1250
TryParse failed, d = 0
42
-17

int.TryParse trả về một bool và ghi kết quả vào một biến out, biến này được đặt về 0 khi thất bại. Vì đầu vào sai là chuyện bình thường với bất cứ thứ gì người dùng gõ, TryParse là lựa chọn mặc định cho đầu vào, tệp và query string. Mọi kiểu số đều có các phương thức tương tự: long.TryParse, double.TryParse, decimal.Parse, và cứ thế.

Mỗi cách xử lý đầu vào sai ra sao

Ba phương thức chỉ khác nhau ở cách chúng thất bại:

Đầu ra:

int.Parse(null) throws ArgumentNullException
Convert.ToInt32(null) = 0
int.Parse("abc") throws FormatException
int.Parse("12.5") throws FormatException
int.Parse("1,000") throws FormatException
int.Parse("9999999999") throws OverflowException
int.Parse("") throws FormatException

FormatException mang thông báo quen thuộc "Input string was not in a correct format" (trên .NET 8 trở lên là "The input string '12.5' was not in a correct format", có trích lại văn bản), và đây là một trong những lỗi lúc chạy phổ biến nhất của C#: "12.5" không phải là int, "1,000" cũng vậy. Để chấp nhận những chuỗi đó, hãy parse thành decimal, hoặc cho trình parse biết những định dạng nào được phép:

Đầu ra:

1000
255
13
10

Culture: vì sao "1.5" có thể thành 15

Mặc định việc parse dùng culture hiện tại, mà các culture lại không thống nhất về dấu phân cách. Trong tiếng Đức và một số culture châu Âu khác, dấu thập phân là dấu phẩy còn dấu chấm dùng để nhóm hàng nghìn (tiếng Việt cũng vậy). Cùng một chuỗi cho ra những con số khác nhau:

Đầu ra:

1.5
15
1.5

Code đọc tệp dữ liệu, JSON, cấu hình hay bất cứ thứ gì do máy tạo ra nên luôn truyền CultureInfo.InvariantCulture, cả khi parse lẫn khi định dạng. Nếu không, cùng một chương trình chạy đúng trên máy lập trình viên nhưng lại đọc sai mọi con số trên một máy chủ đặt ngôn ngữ khác. Chỉ dùng culture hiện tại cho văn bản do người gõ vào hoặc người sẽ đọc.

Chuyển đổi số ngầm định và tường minh

Các phép chuyển đổi mở rộng diễn ra ngầm định: int sang long, int sang double, float sang double, int sang decimal. Một phép chuyển đổi có thể làm mất độ lớn của giá trị hoặc phần thập phân thì cần ép kiểu tường minh (type)value. Có một ngoại lệ cần nhớ: int hoặc long sang float, và long sang double, là ngầm định dù có thể mất độ chính xác: float f = 16_777_217; vẫn biên dịch được và lưu giá trị 16777216.

Đầu ra:

9 -9
10
2
4
705032704
9.99
7 7.0 7

Có ba điều cần nhớ. Ép từ số thực sang số nguyên sẽ cắt bỏ phần thập phân; nó không làm tròn. Convert.ToInt32(double) thì làm tròn, theo kiểu làm tròn ngân hàng (số .5 làm tròn về số chẵn gần nhất). Và một phép ép kiểu số nguyên không vừa sẽ lặng lẽ quay vòng giá trị, trừ khi nó chạy trong ngữ cảnh checked, nơi nó ném OverflowException (xem kiểu dữ liệu).

int x = 3.7; là lỗi biên dịch (CS0266: cannot implicitly convert type 'double' to 'int', an explicit conversion exists), tức là trình biên dịch đang yêu cầu bạn chọn giữa ép kiểu và một phương thức làm tròn.

Chuyển số và các kiểu khác sang string

Mọi kiểu đều có ToString(), và các kiểu số nhận thêm một chuỗi định dạng. String interpolation gọi đến cùng cơ chế định dạng đó:

Đầu ra:

42
000042
1234.50
1,234.50
$1,234.50
FF
1010
True
Order 000042: 1234.50

Các mã định dạng (D, F, N, C, X, P, E) và các mẫu tự định nghĩa như "0.00" được giải thích ở trang string interpolation.

Ký tự và boolean

Đầu ra:

7
55
7
7
A
True
False
1
False

(int)'7' là 55, tức mã của ký tự, không phải 7. Điều này hay làm vấp những ai cộng các chữ số của một số; hãy trừ đi '0' hoặc dùng char.GetNumericValue. bool.Parse nhận "true" và "false" ở bất kỳ kiểu chữ hoa thường nào, và không nhận gì khác ("yes" và "1" đều ném ngoại lệ).

Chuyển đổi kiểu tham chiếu: ép kiểu, as và is

Với kiểu lớp, phép ép kiểu kiểm tra kiểu thực của đối tượng lúc chạy. Ép lên lớp cha (upcast) là ngầm định. Ép xuống lớp con (downcast) cần ép kiểu tường minh, và sẽ ném InvalidCastException khi đối tượng thuộc kiểu khác:

Đầu ra:

4242
True
Card ending 4242, 50.00
InvalidCastException
5
cannot unbox int as long

Hãy ưu tiên is kèm một biến khi bạn cần rẽ nhánh theo kiểu; đó là một lần kiểm tra, không thể ném ngoại lệ, và biến mới chỉ nằm trong phạm vi nơi phép kiểm tra thành công. Dùng ép kiểu thông thường khi một kiểu khác là bug và cần báo lỗi thật rõ. Trường hợp int bị boxing hay làm vấp những ai đọc số từ collection kiểu object hoặc ô của DataRow: hãy unbox về đúng kiểu trước ((long)(int)boxed), hoặc dùng Convert.ToInt64(boxed), hàm này xử lý được mọi kiểu số.

Câu hỏi thường gặp

Làm sao chuyển một chuỗi sang int trong C#?

Dùng int.TryParse(text, out int number) khi văn bản đến từ người dùng, một tệp hoặc qua mạng: nó trả về false thay vì ném ngoại lệ khi văn bản không phải là số hợp lệ. Dùng int.Parse(text) khi văn bản sai là một bug và ném ngoại lệ là phản ứng đúng. Convert.ToInt32(text) hoạt động giống int.Parse, chỉ khác là nó trả về 0 với null.

int.Parse và Convert.ToInt32 khác nhau thế nào?

Với chuỗi, chúng gần như giống nhau: cả hai đều ném FormatException với văn bản kiểu "abc" và OverflowException với số vượt quá giới hạn. Khác biệt nằm ở null: int.Parse(null) ném ArgumentNullException, còn Convert.ToInt32(null) trả về 0. Convert.ToInt32 còn nhận các kiểu khác (double, bool, object), và làm tròn một double về số nguyên chẵn gần nhất thay vì cắt bỏ phần thập phân.

"Input string was not in a correct format" nghĩa là gì?

Đó là thông báo của một FormatException do int.Parse, double.Parse hoặc Convert.ToInt32 ném ra (trên .NET 8 trở lên, thông báo là "The input string 'abc' was not in a correct format", có trích lại văn bản) khi văn bản không phải là số theo định dạng mong đợi: có chữ cái, chuỗi rỗng, có dấu thập phân khi parse một int, hoặc có dấu phân cách hàng nghìn. Hãy chuyển sang TryParse để xử lý đầu vào sai mà không cần ngoại lệ, và kiểm tra xem số được viết theo culture nào.

Làm sao ép một double sang int trong C#?

Viết một phép ép kiểu tường minh: int n = (int)price;. Phép ép này cắt bỏ phần thập phân về phía 0, nên (int)9.99 là 9 và (int)-9.99 là -9. Để làm tròn, hãy dùng (int)Math.Round(price), và lưu ý rằng Math.Round mặc định làm tròn số .5 về số chẵn gần nhất; truyền MidpointRounding.AwayFromZero để làm tròn như ở trường học.

as và ép kiểu trong C# khác nhau thế nào?

Phép ép kiểu (Dog)animal ném InvalidCastException nếu đối tượng không phải là Dog. animal as Dog thì trả về null, nên phải có một bước kiểm tra null theo sau, và nó chỉ dùng được với kiểu tham chiếu và kiểu nullable. Cách hiện đại hơn là pattern is: if (animal is Dog dog) { ... } vừa kiểm tra vừa chuyển đổi trong một bước.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu