GT C Sharp cơ bản – Bài 3 : Chương 3:  Làm quen với C#

0
(0)

Chương 3:  Làm quen với C#

 

Tác giả: Sưu tầm

 

Khái quát

Chương này sẽ giới thiệu nhanh khái quát về ngôn ngữ C#. Chương này giả định là bạn đã có một kiến thức lập trình nhất định và do đó không giới thiệu một cách quá chi tiết. Nếu những giải thích ở đây không thoả mãn các bạn, thì hãy tìm kiếm những giải thích chi tiết hơn ở phần sau trong sách này.

 

Hello, Universe

Như một người ủng hộ SETI (Search for Extraterrestrial Intelligence – Tìm kiếm trí tuệ ngoài trái đất), tôi nghĩ rằng làm một chương trình “Hello, Universe” thích hợp hơn làm chương trình “Hello, World” theo quy tắc.

using System;

 

class Hello {

     public static void Main(string[] args) {

          Console.WriteLine(“Hello, Universe”);

               // quét một vòng qua các đối số dòng lệnh,

               // và in chúng ra

          for (int arg = 0; arg < args.Length; arg++)

               Console.WriteLine(“Arg {0}: {1}”, arg, args[arg]);

     }

}

Như đã nói trước đây, thời gian chạy .NET có một không gian tên (namespace) thống nhất cho tất cả thông tin chương trình (hay dữ liệu mêta). Câu lệnh using System là một cách tham chiếu tới các lớp bên trong không gian tên System cho nên chúng có thể được sử dụng mà không phải đặt System trước tên kiểu (the type name). Không gian tên System chứa nhiều lớp hữu ích, một trong số đó là lớp Console, lớp này được sử dụng (một cách không ngạc nhiên) để giao tiếp với việc nhập xuất Console (hay cửa sổ DOS, hay dòng lệnh).

Bởi vì không có một hàm toàn cục trong C#, cho nên như trong ví dụ đã viết ở trên một lớp Hello chứa một hàm tĩnh Main(), nó được coi là điểm bắt đầu của chương trình thực thi. Hàm Main() có thể được khai báo không có tham số, hoặc nếu có thì là mảng các chuỗi. Vì nó là hàm bắt đầu nên nó phải là hàm tĩnh, có nghĩa là nó không liên kết với một thể hiện của một đối tượng.

Dòng đầu tiên của hàm là lời gọi hàm WriteLine() của lớp Console, để viết ra màn hình dòng chữ “Hello, Universe”. Vòng lặp for duyệt một vòng qua tham số được truyền vào, và sau đó viết các đối số ra màn hình.

 

Không gian tên và câu lệnh using

Không gian tên trong thời gian chạy .NET thường được dùng để tổ chức các lớp và những kiểu khác nhau trong một cấu trúc phân cấp đơn giản. Sử dụng chính xác không gian tên sẽ làm cho các lớp dễ sử dụng và ngăn ngừa những xung đột giữa các lớp được viết bởi người khác.

 

Không gian tên cũng được dùng tới khi một tên lớp hay kiểu quá dài mà không cần phải viết đầy đủ tên của chúng.

Không gian tên được định nghĩa băng cách sử dụng câu lệnh namespace. Đối với cách tổ chức nhiều cấp, thì không gian tên có thể lồng vào nhau:

namespace Outer {

     namespace Inner {

          class MyClass {

               public static void Function() {}

          }

     }

}

Trên chỉ là một cách viết, ta có thể đơn giản hoá bằng cách viết như sau:

namespace Outer.Inner {

     class MyClass {

          public static void Function() {}

     }

}

Mỗi tập tin nguồn có thể định nghĩa bằng nhiều không gian tên khác nhau khi cần.

Như đã đề cập trong phần “Hello, Universe” , using cho phép người sử dụng bỏ qua các không gian tên khi sử dụng một kiểu, để mà các kiểu có thể được tham chiếu dễ dàng hơn.

Using đơn thuần là một cách tắt để giảm bớt việc phải gõ đầy đủ thành phần khi muốn tham chiếu đến những thành phần bên trong không gian tên được nêu trong câu lệnh using, như bảng sau chỉ rõ:

 

Câu lệnh Using

Câu lệnh trong chương trình

Không có

System.Console.WriteLine(“Hello”);

using System

Console.WriteLine(“Hello”);

 

Chú ý rằng using không được dùng với tên lớp, cho nên tên lớp có thể bị bỏ qua. Nói cách khác, using System.Console là không được phép.

Những sự xung đột giữa các kiểu và các không gian tên có tên giống nhau luôn luôn có thể được giải quyết bằng một tên được định ngữ đầy đủ (type fully qualified name). Cách viết này có thể là rất dài nếu lớp được tạo ra có cấu trúc lồng nhiều cấp, vì vậy có một cách định nghĩa một bí danh (alias) cho một lớp bằng câu lệnh using:

using ThatConsoleClass = System.Console;

 

class Hello {

     public static void Main() {

          ThatConsoleClass.WriteLine(“Hello”);

     }

}

Để chương trình dễ đọc hơn, các ví dụ trong sách này hiếm khi sử dụng không gian tên, nhưng chúng nên được dùng trong chương trình thực tế.

 

Không gian tên và hợp tập

Một đối tượng có thể được sử dụng bên trong một tập tin nguồn C# chỉ nếu đối tượng đó có thể được định vị bởi một trình biên dịch C#. Theo mặc định, thì trình biên dịch sẽ chỉ mở một hợp tập đơn là mscorlib.dll, nó chứa những hàm lõi cho môi trường thực thi CLR.

Để tham chiếu những đối tượng đã được định vị trong những hợp tập khác, thì tên của tập tin hợp tập phải được trao cho trình biên dịch. Điều này có thể làm được bằng dòng lệnh sử dụng tuỳ chọn /r:<assembly>, hoặc có thể làm bên trong Visual Studio IDE bằng cách Add Reference cho dự án C#.

Đặc biệt, có sự tương quan giữa không gian tên mà một đối tượng là ở trong đó với tên của một hợp tập mà đối tượng đó đang tồn tại. Ví dụ, những kiểu bên trong không gian tên System.NET là có mặt bên trong hợp tập System.Net.dll. Các kiểu là thường được đặt trong các hợp tập trên cơ sở việc sử dụng những mẫu của những đối tượng trong hợp tập đó; một kiểu được sử dụng nhiều hay ít trong một không gian tên có thể được đặt trong hợp tập riêng của nó.

 

Tên chính xác của hợp tập mà một đối tượng được chứa trong đó có thể được tìm thấy trong tài liệu về đối tượng đó.

 

Các kiểu dữ liệu cơ bản

C# cung cấp một tập hợp những kiểu dữ liệu thông thường. Đối với mỗi kiểu dữ liệu được C# cung cấp, thì bên trong môi trường thực thi CLR có một kiểu tương ứng. Ví dụ, kiểu int trong C# tương ứng với kiểu System.Int32 trong thời gian chạy. System.Int32 có thể được sử dụng trong hầu hết những nơi mà int được dùng, nhưng cách này sẽ không được giới thiệu vì nó sẽ làm cho chương trình khó đọc.

Những kiểu cơ bản là được mô tả trong bảng sau. Các kiểu thời gian chạy có thể được tìm thấy trong không gian tên System của môi trường thực thi CLR .NET.

 

Kiểu

Bytes

Kiểu thời gian chạy

Mô tả

Byte

1

Byte

Kiểu byte không dấu

Sbyte

1

SByte

Kiểu byte có dấu

Short

2

Int16

Kiểu short có dấu

Ushort

2

UInt16

Kiểu short không dấu

Int

4

Int32

Kiểu integer có dấu

Uint

4

UInt32

Kiểu int không dấu

Long

8

Int64

Kiểu long có dấu

Ulong

8

UInt64

Kiểu long không dấu

Float

4

Single

Kiểu dấu chấm động

Double

8

Double

Kiểu double

Decimal

8

Decimal

Kiểu decimal

String

 

String

Chuỗi unicode

Char

 

Char

Ký tự unicode

Bool

 

Boolean

Kiểu boolean

 

Sự phân biệt giữa những kiểu cơ bản (hay kiểu có sẵn) trong C# và kiểu do lập trình viên tạo ra là rất lớn, tuy kiểu do người sử dụng tạo ra là có thể được xử lý với cùng dạng như một kiểu có sẵn. Thật ra, sự khác nhau thực tế giữa những kiểu dữ liệu có sẵn và những kiểu dữ liệu người sử dụng định nghĩa là nó có thể viết những giá trị đúng cho những kiểu có sẵn.

 

Kiểu dữ liệu được chia thành kiểu giá trị (value type) và kiểu tham chiếu (reference type). Kiểu giá trị là được cấp phát theo dạng stack hay được cấp phát inline trong một cấu trúc. Kiểu tham chiếu thì được cấp phát theo dạng heap.

 

Cả kiểu tham chiếu và kiểu giá trị là đều được dẫn xuất từ lớp cơ sở tận cùng object. Trong những trường hợp mà một kiểu giá trị cần được coi như một object, thì một trình bao bọc (wrapper) sẽ làm cho kiểu giá trị trở thành đối tượng tham chiếu được cấp phát trong heap, và giá trị của kiểu giá trị là được sao chép vào trong đó. Trình bao bọc là được đánh dấu cho nên hệ thống biết là nó chứa một giá trị kiểu int. Cách thức này được gọi là đóng hộp (boxing), và ngược lại là tháo hộp (unboxing). Hai cách thức trên cho bạn cách đối xử với bất kỳ kiểu nào như một object. Điều đó cho phép bạn có thể viết như sau:

using System;

 

class Hello {

     public static void Main(string[] args) {

          Console.WriteLine(“Value is: {0}”, 3.ToString());

     }

}

Trong trường hợp này, số nguyên 3 là đã được đóng hộp, và hàm Int32.ToString() là được gọi với giá trị đã được đóng hộp.

Các mảng C# có thể được khai báo nhiều chiều theo hai dạng chữ nhật hoặc răng cưa (jagged). Những cấu trúc dữ liệu tiên tiến hơn, như stack và bảng băm, có thể được tìm thấy trong không gian tên System.Collections.

 

Lớp, cấu trúc, và giao diện

Trong C#, từ khoá class là được dùng để khai báo 1 kiểu tham chiếu (được xác định trong heap), và từ khoá struct là được dùng để khai báo 1 kiểu giá trị. Cấu trúc là được sử dụng cho những đối tượng hạng nhẹ (lightweight) mà chúng cần thao tác như những kiểu có sẵn, và lớp là được dùng cho tất cả các trường hợp còn lại. Ví dụ, kiểu int là 1 kiểu giá trị, và kiểu string là 1 kiểu tham chiếu. Sơ đồ sau trình bày chi tiết điều gì sẽ xảy ra:

int v = 123;

string s = “Hello There”;

123

 

 

v

 

Hello There

 

s

 

Sơ đồ 3-1. Sự xác định kiểu giá trị và kiểu tham chiếu

 

C# và thời gian chạy .NET không hỗ trợ đa thừa kế cho lớp nhưng hỗ trợ đa thừa kế cho cài đặt interface.

 

Câu lệnh

Các câu lệnh trong C# là gần giống với câu lệnh C++, với 1 ít sự cải biên để làm giảm các lỗi, và có thêm 1 số câu lệnh mới. Câu lệnh foreach được sử dụng để duyệt qua các mảng và các sưu tập, câu lệnh lock được sử dụng cho sự loại trừ lẫn nhau trong kịch bản tiểu trình, và câu lệnh checkedunchecked là được dùng để điều khiển kiểm tra sự tràn trong các phép toán số học và các chuyển đổi kiểu.

 

Kiểu liệt kê

Kiểu liệt kê là được sử dụng để khai báo 1 tập hợp các hằng số có liên quan với nhau – như những màu mà 1 điểu khiển cần có – trong khía cạnh rõ ràng và an toàn về kiểu. Ví dụ:

enum Colors {

     red,

     green,

     blue

}

Kiểu liệt kê sẽ được nói kỹ hơn ở Chương 20,“Kiểu liệt kê”.

 

Thẻ uỷ quyền và sự kiện

Thẻ uỷ quyền là một kiểu an toàn, những con trỏ thực thi hàm được hướng đối tượng và được sử dụng trong nhiều tình huống mà một thành phần cần gọi lại đến một thành phần đang sử dụng nó. Đó chính là cơ sở của sự kiện, cái cho phép một thẻ uỷ quyền được dễ dàng đăng ký cho một sự kiện. Chúng ta sẽ bàn đến vấn đề này tại Chương 22,”Thẻ uỷ quyền”.

 

Thẻ uỷ quyền và sự kiện là được sử dụng nhiều trong .NET Frameworks.

 

Thuộc tính và chỉ mục

C# hỗ trợ thuộc tính và chỉ mục, nó hữu ích để phân biệt giao diện của một đối tượng với cài đặt của đối tượng đó. Thay vì cho phép người sử dụng truy nhập một trường hay mảng một cách trực tiếp, một thuộc tính hay chỉ mục cho phép một khối câu lệnh xác định để thực hiện việc truy nhập, trong khi vẫn cho phép việc sử dụng trường và mảng. Đây là một ví dụ đơn giản:

using System;

 

class Circle {

     public int X {

          get {

               return(x);

          }

          set {

               x = value;// gán giá trị cho đối tượng tại đây.

          }

     }

 

    int x;

}

 

class Test {

     public static void Main() {

          Circle c = new Circle();

          c.X = 35;

     }

}

Trong ví dụ này, hàm truy nhập getset là được gọi khi 1 thuộc tính X là được tham chiếu.

 

Các đặc tính

Các đặc tính được dùng trong C# và .NET Frameworks để truyền những thông tin khai báo từ người viết mã đến mã khác quan tâm đến thông tin. Điều này có thể được sử dụng để chỉ rõ các trường của một đối tượng phải được xếp thứ tự, nội dung giao dịch gì là được sử dụng khi đang thực thi một đối tượng, làm sao để sắp xếp các trường bằng những hàm cơ bản, hay làm sao để hiển thị một lớp trong một bộ duyệt lớp.

 

Những đặc tính được chỉ rõ bên trong những dấu ngoặc vuông. Ta có thể viết một đặc tính như sau: [CodeReview(“12/31/1999“, Comment=”Well done”)]

 

Thông tin đặc tính là được lấy ra khi thực hiện thông qua phép phản chiếu. Những đặc tính mới có thể được viết một cách dễ dàng, được gắn vào những thành phần của mã (như lớp, thành phần, hay tham số), và được lấy ra thông qua phép phản chiếu.

 

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Related posts

GT C Sharp cơ bản – Bài 30 : Chương 29:  So sánh C# với các ngôn ngữ khác

GT C Sharp cơ bản – Bài 29 : Chương 28: Dòng lệnh

GT C Sharp cơ bản – Bài 28 : Chương 27: Tính tương hoạt