Các Chủ Đề Tiến Bộ Trong C# part 2
lượt xem 6
download
Các ép kiểu do người dùng định nghĩa Trong các chương trước ta được học về cách chuyển đổi giá trị giữa những kiểu dữ liệu cơ bản. chúng ta cũng đã học hai cách ép kiểu là : - Không tường minh (Implicit)
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Các Chủ Đề Tiến Bộ Trong C# part 2
- Các ép kiểu do người dùng định nghĩa Trong các chương trước ta được học về cách chuyển đổi giá trị giữa những kiểu dữ liệu cơ bản. chúng ta cũng đã học hai cách ép kiểu là : - Không tường minh (Implicit) - Tường minh (Explicit) Vì c# cho phép ta định nghĩa những lớp và cấu trúc riêng,do đó ta cũng muốn có những cách thức mà cho phép ta chuyển đổi giữa những loại dữ liệu của riêng ta. C# cho phép làm điều đó.cơ chế của nó là ta có thể định nghĩa một ép kiểu như là một thao tác thành viên của một trong những lớp thích hợp. việc ép kiểu phải được đánh dấu là implicit hoặc explicit để chỉ định cách mà bạn muốn sử dụng với nó. cũng giống như việc ép kiểu cơ bản : nếu bạn biết việc ép kiểu là an toàn ,dù là bất cứ giá trị nào đựợc giữ bởi biến nguồn, thì bạn định nghĩa nó như là implicit.ngược lại nếu bạn biết việc ép kiểu có thể đi đến sự liều lĩnh - mất dữ liệu hay một biệt lệ sẽ bị tung ra - bạn nên định nghĩa ép kiểu như là explicit. Bạn nên định nghĩa bất kỳ kiểu ép kiểu mà bạn viết là tường minh nếu có bất kì giá trị dữ liệu nguồn nào mà việc ép kiểu có khả năng thất bại, hoặc nếu có sự mạo hiểm do một biệt lệ được tung ra. Cú pháp của việc định nghĩa ép kiểu cũng giống như việc overload thao tác . không phải ngẫu nhiên mà ta nói thế , bởi vì theo cách mà ép kiểu được xem như là thao tác là tác động của nó là chuyển từ kiểu dữ liệu nguồn sang kiểu dữ liệu đích. để minh hoạ cho cú pháp này, cú pháp sau được lấy từ ví dụ mà sẽ được giới thiệu sau đây trong phần này: public static implicit operator float (Currency value) { // xử lí } Đoạn mã này là một phần của cấu trúc - currency - được dùng để lưu trữ tiền.ép kiểu được định nghĩa ở đây cho phép chúng ta chuyển đổi 1 cách ẩn dụ giá trị của 1 kiểu tiền tệ sang 1 số thực ( float). chú ý rằng nếu việc chuyển được khai báo như là implicit, thì trình biên dịch cho phép nó sử dụng cả implicit và explicit. nếu nó được khai báo như là explicit , thì trình biên dịch chỉ cho phép nó sử dụng như là explicit. Trong khai báo này việc ép kiểu được khai báo là static. giống như các thao tác được overload , C# đòi hỏi việc ép kiểu là static. điều này có nghĩa là mỗi ép kiểu cũng lấy một thông số , mà là kiểu dữ liệu trong nguồn Thực hành ép kiểu dữ liệu do người sử dụng định nghĩa. Trong phần này, chúng ta sẽ xem xét việc ép kiểu implicit và explicit của kiểu dữ liệu này trong ví dụ Simplecurrency. trong ví dụ này chúng ta định nghĩa 1 cấu trúc struct, currency, mà giữ tiền USA. thông thường, C# cung cấp kiểu thập phân ( decimal) cho mục đích này, nhưng bạn vẫn có thể viết riêng 1 cấu trúc struct hay một lớp để trình bày giá trị tiền nếu bạn muốn biểu diễn quy trình tài chính phức tạp và do đó muốn có một phương thức cụ thể để thực thi như là một lớp.
- cấu trúc của ép kiểu là giống nhau cho struct hay lớp . trong ví dụ này là struct, nhưng nó cũng làm việc tốt nếu bạn khai báo currency như là một lớp. khởi đầu , định nghĩa cấu trúc currency như sau: struct Currency { public uint Dollars; public ushort Cents; public Currency(uint dollars, ushort cents) { this.Dollars = dollars; this.Cents = cents; } Việc dùng kiểu dữ liệu không dấu cho trường Dollar và cent bảo đảm rằng một thể hiện của currency chỉ giữ 1 số dương.chúng ta giới hạn nó bằng cách này để có thể minh hoạ một số điểm về tường minh sau này.để giữ cho lớp đơn giản,ta chọn các trường là public, nhưng nói chung bạn sẽ phải định nghĩa chúng private, và định nghĩa những thuộc tính đáp ứng cho dollar và cent Chúng ta hãy bắt đầu bằng cách giả sử như là bạn muốn chuyển giá trị từ currency sang float, mà phần nguyên của kiểu float sẽ trình bày dollar: Currency balance = new Currency(10,50); float f = balance; // ta muốn f được đặt là 10.5 Để cho phép làm điều này , cần định nghĩa 1 ép kiểu. từ đây ta thêm vào trong cấu trúc currency: public static implicit operator float (Currency value) { return value.Dollars + (value.Cents/100.0f); } Ép kiểu này là implicit, Đây là sự chọn lựa dễ nhận thấy , bởi vì , nó nên rõ ràng từ định nghĩa trong currency, bất kì giá trị nào lưu trữ trong currency cũng có thể lưu trong kiểu float. Nếu chuyển ngược thì sao? từ một số float sang currency .trong trường hợp này việc chuyển đổi có thể không làm việc ,nếu float lưu trữ số âm,còn currency thì không , và số này sẽ lưu trữ phần làm tròn vào trong trường dollar của currency.nếu float chứa đựng một giá trị không thích hợp việc chuyển nó sẽ gây ra một kết quả không dự đoán truớc. do đó việc chuyển đổi này nên được khai báo là explicit. sau đây là đoạn mã thử đầu tiên , tuy nhiên nó không gửi kết quả hoàn toàn đúng: public static explicit operator Currency (float value) { uint dollars = (uint)value; ushort cents = (ushort)((value-dollars)*100); return new Currency(dollars, cents); }
- Đoạn mã sau sẽ dịch đúng : float amount = 45.63f; Currency amount2 = (Currency)amount; Tuy nhiên đoạn mã sau sẽ báo lỗi bởi vì nó sử dụng một ép kiểu tường mình một cách không rõ ràng : float amount = 45.63f; Currency amount2 = amount; // sai Sau đây là phương thức main() mà khởi tạo một struct Currency, và thực hiện một vài việc chuyển đổi. vào đầu đoạn mã, chúng ta viết giá trị của biến balance theo 2 cách ( để minh họa 1 số điều cho phần sau) static void Main() { try { Currency balance = new Currency(50,35); Console.WriteLine(balance); Console.WriteLine("balance is " + balance); Console.WriteLine("balance is (using ToString()) " + balance.ToString()); float balance2= balance; Console.WriteLine("After converting to float, = " + balance2); balance = (Currency) balance2; Console.WriteLine("After converting back to Currency, = " + balance); Console.WriteLine("Now attempt to convert out of range value of " + "-$100.00 to a Currency:"); checked { balance = (Currency) (-50.5); Console.WriteLine("Result is " + balance.ToString()); } } catch(Exception e) { Console.WriteLine("Exception occurred: " + e.Message); } } Chú ý rằng ta đặt toàn bộ đoạn mã trong khối try để bắt bất cứ biệt lệ nào xảy ra trong quá trình ép kiểu. Sau khi chạy ta có kết quả sau :
- SimpleCurrency 50.35 Balance is $50.35 Balance is (using ToString()) $50.35 After converting to float, = 50.35 After converting back to Currency, = $50.34 Now attempt to convert out of range value of -$100.00 to a Currency: Result is $4294967246.60486 Kết quả cho thấy đoạn mã không làm việc như mong đợi. ở phần đầu việc chuyển cho kết quả sai là 50.34 thay vì 50.35. trong phần hai, không có biệt lệ nào được sinh ra khi ta cố chuyển một giá trị nằm ngoài vùng. Lỗi dầu tiên là do làm tròn.. nếu ép kiểu từ float sang uint , máy tính sẽ cắt bỏ số hơn là làm tròn nó.máy tính lưu trữ số dạng nhị phân hơn là thập phân.và phần dư 0.35 không thể được trình bày một cách chính xác như là phần dư dạng nhị phân.do đó máy tính lưu trữ một số nhỏ hơn 0.35, mà có thể trình bày chính xác trong dạng nhị phân.nhân cho 100 và lấy phần dư nhỏ hơn 35 cắt thành 34 cent.rõ ràng trong hoàn cảnh này, lỗi cắt bỏ là nghiêm trọng.để tránh chúng thì chắc rằng một sự làm tròn thông minh phải được thi hành trong việc chuyển đổi số.thật may mắn Microsoft đã viết một lớp để làm điều đó : System.Convert . System.Convert chứa đựng một số lượng lớn những phương thức static biểu diễn việc chuyển đổi số, và Phương thức mà chúng ta muốn là System.convert.Uint6(). Bây giờ chúng ta sẽ kiểm tra xem tại sao biệt lệ tràn đã không xuất hiện . vấn đề ở đây là : nơi mà việc tràn xuất hiện không thực sự nằm trong hàm main()- nó ở bên trong mã của thao tác ép kiểu. mà được gọi từ phương thức main() . và chúng ta đã không kiểm tra đoạn mã đó. Giải pháp ở đây là cho phép kiểm tra ngay trong hàm ép kiểu public static explicit operator Currency (float value) { checked { uint dollars = (uint)value; ushort cents = Convert.ToUInt16((value-dollars)*100); return new Currency(dollars, cents); } } Chú ý rằng ta sử dụng convert.uint16() để tính phần xu thay cho đoạn mã trên.ta không cần dùng cách này để tính phần dollar vì việc cắt bỏ trong giá trị float đã đưa ra kết quả ta cần Ép kiểu giữa những lớp Ví dụ trên cho ta thấy việc ép kiểu giữa 2 kiểu dữ liệu đã được định nghĩa trước.tuy nhiên ta cũng có thể ép kiểu giữa 2 cấu trúc hoặc lớp mà ta định nghĩa. có 2 hạn chế cần quan tâm :
- - Ta không thể định nghĩa một ép kiểu nếu một trong những lớp được dẫn xuất từ 1 lớp khác. - Ép kiểu phải được định nghĩa bên trong việc định kiểu dữ liệu nguồn hay đích. Để minh hoạ những yêu cầu này , giả sử rằng ta có biểu đồ lớp sau: Nói cách khác,lớp c và d được dẫn xuất gián tiếp từ lớp a.trong trường hợp này,chỉ có những ép kiểu riêng giữa a,b,c,d mà hợp pháp sẽ được chuyển là những lớp c và d bởi vì những những lớp này không được dẫn xuất từ mỗi lớp khác.mã có thể như sau : public static explicit operator D(C value) { // and so on } public static explicit operator C(D value) { // and so on } Cho mỗi kiểu ép kiểu này , ta có quyền chọn nơi mà ta đặt định nghĩa- bên trong lớp định nghĩa C hoặc bên trong lớp định nghĩa D, nhưng không nằm ở bất cứ chổ nào khác.C# đòi hỏi bạn đặt định nghĩa của 1 ép kiểu bên trong lớp ( hoặc cấu trúc)nguồn hoặc bên trong lớp ( hoặc cấu trúc) đích Mỗi lần bạn định nghĩa một ép kiểu bên trong 1 lớp , bạn không thể định nghĩa giống như vậy bên trong những lớp khác.rõ ràng, chỉ nên có 1 hàm ép kiểu cho mỗi chuyển đổi. nếu không trình biên dịch không biết sử dụng cái nào. Ép kiểu giữa lớp dẫn xuất và lớp cơ sở Để xem làm thế nào việc ép kiểu này làm, ta xem xét 2 lớp Mybase và Myderived , trong đó Mydrived được dẫn xuất trực tiếp hoặc gián tiếp từ lớp cơ sở đầu tiên từ lớp Myderived đến Mybase ; luôn luôn ( giả sử hàm dựng có giá trị)có thể viết : MyDerived derivedObject = new MyDerived(); MyBase baseCopy = derivedObject;
- Trong trường hợp này,chúng ta ép kiểu không tường minh từ myderived đến mybase. điều này làm việc bởi vì luật là bất kì tham chiếu đến 1 kiểu mybase được cho phép để chuyển thành đối tượng của lớp mybase hoặc đến đối tượng bất kì được dẫn xuất từ lớp mybase.trong ngôn ngữ lập trình hướng đối tượng, thể hiện của lớp dẫn xuất là thể hiện của một lớp cơ sở cộng thêm với một thứ gì đó thêm. tất cả chức năng và thuộc tính được định nghĩa trong lớp cơ sở cũng được định nghĩa trong lớp dẫn xuất . Bây giờ ta có thể viết MyBase derivedObject = new MyDerived(); MyBase baseObject = new MyBase(); MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK MyDerived derivedCopy2 = (MyDerived) baseObject; Tất cả các câu lệnh trên là hợp lệ trong C# và minh họa việc ép kiểu từ lớp cơ sở sang lớp dẫn xuất. tuy nhiên câu lệnh cuối sẽ tung ra biệt lệ khi thực thi. Chú ý rằng những lệnh ép kiểu mà trình biên dịch cung cấp , mà chuyển giữa lớp cơ sở và lớp dẫn xuất thì không thực sự chuyển bất cứ dữ liệu nào trên các đối tượng.tất cả chúng làm là thiết lập một sự tham chiếu mới để quy cho một đối tượng nếu nó hợp lệ cho việc chuyển đổi .những lệnh ép kiểu này thì rất khác trong tự nhiên từ những cái mà ta thường xuyên tự định nghĩa.ví dụ, trong ví dụ Simplecurrency chúng ta định nghĩa việc ép kiểu là chuyển giữa 1 kiểu tiền tệ sang kiểu số thực. trong ép kiểu thực-thành- currency, chúng ta thực sự tạo một cấu trúc currency mới và khởi tạo nó với giá trị được yêu cầu .những lệnh ép kiểu tiền định nghĩa giữa những lớp cơ s ở và lớp dẫn xuất không làm điều này.nếu ta thực sự chuyển 1 thể hiện Mybase thành một đối tượng Myderived thực với giá trị dựa trên nội dung của thể hiện Mybase, ta sẽ không thể sử dụng cú pháp ép kiểu để làm điều này.tuỳ chọn hợp lí nhất là thường xuyên định nghĩa 1 hàm dựng của lớp dẫn xuất mà lấy thể hiện của lớp cơ sở như là 1 thông số và có hàm dựng này biểu diễn việc khởi tạo chính xác: class DerivedClass : BaseClass { public DerivedClass(BaseClass rhs) { // khởi tạo đối tượng từ thể hiện Base } // etc. Ép kiểu boxing và unboxing Ví dụ với cấu trúc currency: Currency balance = new Currency(40,0); object baseCopy = balance; Khi ép kiểu không tường minh trên được thực hiện nội dung của balance được sao chép vào heap trong đối tượng box và đối tượng basecopy tham khảo đến đối tượng này.khi chúng ta định nghĩa cấu trúc currency , .net framework cung cấp không tường minh một lớp ( ẩn) khác , một lớp currency boxed, mà chứa đựng tất cả các trường như là cấu trúc currency nhưng là kiểu tham chiếu lưu trong heap.điều này xảy ra bất cứ khi nào chúng ta
- định nghĩa một kiểu dữ liệu- dù đó là struct hay kiểu liệt kê ( enum) ,và kiểu tham khảo boxed tồn tại đáp ứng đến tất cả kiểu dữ liệu nguyên thuỷ int,double,uint, và ...ta không thể truy nhập vào các lớp này nhưng chúng sẽ làm việc bất cứ khi nào có việc ép kiểu thành đối tượng khi chúng ta ép kiểu currency thành đối tượng một thể hiện currency boxed tạo ra và khởi tạo với tất cả các giá trị từ cấu trúc currency. trong ví dụ trên basecopy sẽ tham khảo đến lớp currency boxed. Ép kiểu còn được biết đến như là unboxing,dùng cho việc ép kiểu giữa những lớp kiểu tham chiếu cơ sở và kiểu tham chiếu dẫn xuất.đó là ép kiểu tường minh, bởi vì 1 biệt lệ sẽ được tung ra nếu đối tượng được ép kiểu không ép đúng. object derivedObject = new Currency(40,0); object baseObject = new object(); Currency derivedCopy1 = (Currency)derivedObject; // OK Currency derivedCopy2 = (Currency)baseObject; // Exception thrown Khi sử dụng boxing và unboxing điều quan trọng để hiểu là cả hai tiến trình này thực sự sao chép dữ liệu vào một đối tượng boxed hay unboxed. chính vì lí do đó, thao tác trên đối tượng hộp sẽ không tácđộng đến nội dung của kiểu dữ liệu nguyên thuỷ. Multiple casting Ví dụ với cấu trúc currency , giả sử trình biên dịch chạm trán với các dòng mã sau: Currency balance = new Currency(10,50); long amount = (long)balance; double amountD = balance; Đầu tiên chúng ta khởi tạo 1 thể hiện currency ,sau đó ép nó thành kiểu long.vấn đề là ta chưa định nghĩa ép kiểu cho việc này. tuy nhiên đoạn mã nay vẫn biên dịch thành công bởi vì trình biên dịch nhận ra rằng ta đã định nghĩa ép kiểu không tường minh để chuyển currency thành float.và nó biết cách chuyển tường minh từ float sang long. ví lí do đó, nó sẽ biên dịch đầu tiên là chuyển balance sang float rồi từ float sang long.tương tự cho kiểu double tuy nhiên do chuyển tử float sang double không tường minh , do đó chúng ta có thể viết lại tường minh : Currency balance = new Currency(10,50); long amount = (long)(float)balance; double amountD = (double)(float)balance; Đoạn mã sau gây ra lỗi : Currency balance = new Currency(10,50); long amount = balance; Do việc chuyển từ float sang long cần tường minh. Nếu ta không cẩn thận khi nào ta sẽ định nghĩa ép kiểu, thì trình biên dịch có thể sẽ dẫn đến một kết quả không mong đợi..Ví dụ, giả sử một ai khác trong nhóm đang viết cấu trúc Currency,mà sẽ hửu ích nếu có khả năng chuyển 1 số uint chứa tổng số Cent thành 1
- kiểu Currency ( Cent chứ không phải Dollar bởi vì nó sẽ không làm mất đi phần thập phân của Dollar ) .vì thế việc ép kiểu này có thể được viết như sau : public static implicit operator Currency (uint value) { return new Currency(value/100u, (ushort)(value%100)); } // Don't do this! Lưu ý chữ u sau số 100 đảm bảo rằng value/100u sẽ đuợc phiên dịch thành 1 số uint. nếu ta viết value/100 thì trình biên dịch sẽ phiên dịch sẽ phiên dịch nó là số int chứ không phải uint. Lý do ta không nên viết mã kiểu này là vì : tất cả ta làm trong đó là chuyển 1 uint chứa 350 thành 1 kiểu Currency và ngược trở lại. Ta sẽ có gì sau khi thi hành mã này : uint bal = 350; Currency balance = bal; uint bal2 = (uint)balance; Câu trả lời không phải là 350 mà là 3. Ta chuyển 350 thành 1 Currency 1 cách không tường minh, trả về kết quả Balance.Dollars=3 , Balance.Cents=50. Sau đó trình biên dịch tính toán hướng tốt nhất để chuyển trở lại.Balance được chuyển không tường minh thành 1 kiểu float ( giá trị 3.5) và số này được chuyển tường minh thành 1 số uint với giá trị 3 Vấn đề là có 1 sự xung đột giữa cách các ép kiểu của ta dịch các số nguyên integer.các ép kiểu giữa Currency và float dịch 1 số nguyên giá trị 1 thành 1 doolar, nhưng cách ép kiểu uint-to-Currency cuối nhất sẽ dịch giá trị này là 1 cent.Nếu ta muốn lớp của ta dễ dàng để dùng thì ta nên chắc rằng tất cả các ép kiểu của ta cư xử hợp với nhau,theo hướng cho ra cùng 1 kết quả. Trong trường hợp này ,giải pháp là viết lại hàm ép kiểu uint-to-Balance để nó phiên dịch 1 số nguyên integer giá trị 1 thành 1 dollar. public static implicit operator Currency (uint value) { return new Currency(value, 0); } 1 cách kiểm tra tốt là xét xem 1 chuyển đổi có cho ra cùng kết quả hay không.Lớp Currency đưa ra 1 ví dụ tốt cho kiểm tra này : Currency balance = new Currency(50, 35); ulong bal = (ulong) balance;
- Hiện tại chỉ có 1 cách mà trình biên dịch có thể thực hiện việc chuyển đổi này: bằng cách chuyển Currency thành 1 float 1 cách không tường minh.việc chuyển float thành ulong đòi hỏi 1 sự tường minh. Giả sử ta thêm 1 cách ép kiểu khác,để chuyển 1 cách không tường minh từ Currency thành uint.Ta sẽ làm điều này bằng việc cập nhật lại cấu trúc Currency bằng cách thêm vào các ép kiểu thành và từ kiểu uint. Ta xem đây là ví dụ SimpleCurrency2: public static implicit operator Currency (uint value) { return new Currency(value, 0); } public static implicit operator uint (Currency value) { return value.Dollars; } Bây giờ trình biên dịch có 1 cách khác để chuyển từ Currency thành ulong: là chuyển từ Currency thành uint 1 cách tường minh sau đó thành ulong 1 cách không tường minh. để kiểm tra ví dụ SimpleCurrency2, ta sẽ thêm đoạn mã này vào phần kiểm tra trong SimpleCurrency: try { Currency balance = new Currency(50,35); Console.WriteLine(balance); Console.WriteLine("balance is " + balance); Console.WriteLine("balance is (using ToString()) " + balance.ToString()); uint balance3 = (uint) balance; Console.WriteLine("Converting to uint gives " + balance3); Chạy ví dụ ta có kết quả SimpleCurrency2 50 balance is $50.35 balance is (using ToString()) $50.35 Converting to uint gives 50 After converting to float, = 50.35 After converting back to Currency, = $50.34 Now attempt to convert out of range value of -$100.00 to a Currency: Exception occurred: Arithmetic operation resulted in an overflow.
- Kết quả chỉ ra việc chuyển đổi thành uint thành công,ta đã mất phần cent của Currency trong việc chuyển này. Ép kểu 1 số float âm thành Currency đã gây ra 1 biệt lệ. Tuy nhiên kết quả cũng giải thích 1 vấn đề nữa mà ta cần nhận thức khi làm việc với ép kiểu.dòng đầu tiên của kết quả không trình bày balance đúng,trình bày 50 thay vì $50.35. Console.WriteLine(balance); Console.WriteLine("balance is " + balance); Console.WriteLine("balance is (using ToString()) " + balance.ToString()); Chỉ có 2 dòng cuối trình bày đúng Currency thành chuỗi.Vấn để ở đây là khi ta kết hợp ép kiểu với phương thức overload,ta lấy 1 nguồn khác không dự đoán trước được.Ta sẽ xem kĩ hơn vấn đề này sau. Câu lệnh thứ 3 Console.WriteLine() gọi tường minh phương thức Currency.ToString() đảm bảo Currency được trình bày là chuỗi.Cái thứ 2 không làm như vậy. tuy nhiên ,chuỗi " balance is" được truyền đến Console.WriteLine làm rõ hơn rằng thông số được phiên dịch như chuỗi. Chính vì vậy Currency,ToString() sẽ được gọi không tường minh. Phương thức Console.WriteLine đầu tiên đơn giản truyền1 cấu trúc Currency đến Console.WriteLine.Console.WriteLine có nhiều hàm overload,nhưng không có cái nào trong chúng lấy cấu trúc Currency .Vì vậy trình biên dịch sẽ bắt đầu tìm xem nó có thể ép Currency thành kiểu nào để làm cho nó phù hợp với overload của Console.WriteLine. khi nó xảy ra , một trong những overload Console.WriteLine() được thiết kế để trình bày uint 1 cách nhanh chóng và hiệu quả, và nó lấy 1 uint như là 1 thông số, và ta vừa cung cấp 1 ép kiểu chuyển Currency thành uint không tường minh.Kết quả là nó có thể trình bày. Quả thực Console.WriteLine có overload khác lấy 1 double làm thông số và trình bày giá trị của double.nếu ta xem kĩ kết quả từ ví dụ SimpleCurrency đầu ta sẽ sẽ thấy dòng kết quả đầu tiên sẽ trình bày Currency như là 1 số double.trong ví dụ đó không có việc ép kiểu trực tiếp từ Currency thàng uint ,vì vậy trình biên dịch sẽ lấy Currency-to-float-to- double để làm. Code for Download: SimpleCurrency SimpleCurrency2
CÓ THỂ BẠN MUỐN DOWNLOAD
-
Bí kíp che giấu và bảo vệ dữ liệu riêng tư
4 p | 438 | 197
-
Các Chủ Đề Tiến Bộ Trong C# part
8 p | 75 | 7
-
Các Chủ Đề Tiến Bộ Trong C# part 7
5 p | 94 | 5
-
Các Chủ Đề Tiến Bộ Trong C# part 8
16 p | 67 | 5
-
Các Chủ Đề Tiến Bộ Trong C# part 9
1 p | 77 | 5
-
Các Chủ Đề Tiến Bộ trong C# part 6
4 p | 64 | 4
-
Các Chủ Đề Tiến Bộ Trong C# part 1
19 p | 71 | 4
-
Các Chủ Đề Tiến Bộ Trong C# part 3
11 p | 50 | 4
-
Các Chủ Đề Tiến Bộ Trong C# part 5
3 p | 94 | 3
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn