C # - Hướng dẫn nhanh
C # là một ngôn ngữ lập trình hiện đại, đa năng, hướng đối tượng được phát triển bởi Microsoft và được Hiệp hội các nhà sản xuất máy tính Châu Âu (ECMA) và Tổ chức Tiêu chuẩn Quốc tế (ISO) phê duyệt.
C # được phát triển bởi Anders Hejlsberg và nhóm của ông trong quá trình phát triển .Net Framework.
C # được thiết kế cho Cơ sở hạ tầng ngôn ngữ chung (CLI), bao gồm mã thực thi và môi trường thời gian chạy cho phép sử dụng nhiều ngôn ngữ cấp cao khác nhau trên các nền tảng và kiến trúc máy tính khác nhau.
Những lý do sau đây khiến C # trở thành một ngôn ngữ chuyên nghiệp được sử dụng rộng rãi -
- Nó là một ngôn ngữ lập trình đa năng, hiện đại
- Nó là hướng đối tượng.
- Nó được định hướng thành phần.
- Nó rất dễ học.
- Nó là một ngôn ngữ có cấu trúc.
- Nó tạo ra các chương trình hiệu quả.
- Nó có thể được biên dịch trên nhiều nền tảng máy tính.
- Nó là một phần của .Net Framework.
Các tính năng lập trình mạnh mẽ của C #
Mặc dù cấu trúc C # bám sát các ngôn ngữ cấp cao truyền thống, C và C ++ và là một ngôn ngữ lập trình hướng đối tượng. Nó có nhiều điểm tương đồng với Java, nó có nhiều tính năng lập trình mạnh mẽ khiến nó được một số lập trình viên trên toàn thế giới yêu thích.
Sau đây là danh sách một số tính năng quan trọng của C #:
- Điều kiện Boolean
- Thu gom rác tự động
- Thư viện tiêu chuẩn
- Phiên bản hội
- Thuộc tính và sự kiện
- Quản lý đại diện và sự kiện
- Generics dễ sử dụng
- Indexers
- Biên soạn có điều kiện
- Đa luồng đơn giản
- Biểu thức LINQ và Lambda
- Tích hợp với Windows
Dùng thử Tùy chọn trực tuyến
Chúng tôi đã thiết lập môi trường Lập trình C # trực tuyến để bạn có thể biên dịch và thực thi tất cả các ví dụ có sẵn trực tuyến. Nó mang lại cho bạn niềm tin vào những gì bạn đang đọc và cho phép bạn xác minh các chương trình bằng các tùy chọn khác nhau. Vui lòng sửa đổi bất kỳ ví dụ nào và thực hiện trực tuyến.
Hãy thử ví dụ sau bằng trình biên dịch trực tuyến của chúng tôi có sẵn tại CodingGround
using System; namespace HelloWorldApplication { class HelloWorld { static void Main(string[] args) { /* my first program in C# */ Console.WriteLine("Hello World"); Console.ReadKey(); } } }
Đối với hầu hết các ví dụ được đưa ra trong hướng dẫn này, bạn sẽ tìm thấy tùy chọn Dùng thử trong phần mã trang web của chúng tôi ở góc trên cùng bên phải sẽ đưa bạn đến trình biên dịch trực tuyến. Vì vậy, chỉ cần tận dụng nó và tận hưởng việc học của bạn.
Trong chương này, chúng ta sẽ thảo luận về các công cụ cần thiết để tạo lập trình C #. Chúng tôi đã đề cập rằng C # là một phần của .Net framework và được sử dụng để viết các ứng dụng .Net. Do đó, trước khi thảo luận về các công cụ có sẵn để chạy chương trình C #, chúng ta hãy hiểu C # liên quan như thế nào với .Net framework.
.Net Framework
.Net framework là một nền tảng cách mạng giúp bạn viết các loại ứng dụng sau:
- Ứng dụng Windows
- Ứng dụng web
- Dịch vụ web
Các ứng dụng .Net framework là các ứng dụng đa nền tảng. Khung công tác đã được thiết kế theo cách mà nó có thể được sử dụng từ bất kỳ ngôn ngữ nào sau đây: C #, C ++, Visual Basic, Jscript, COBOL, v.v. Tất cả những ngôn ngữ này có thể truy cập khung công tác cũng như giao tiếp với nhau.
Khuôn khổ .Net bao gồm một thư viện mã khổng lồ được sử dụng bởi các ngôn ngữ khách như C #. Sau đây là một số thành phần của .Net framework:
- Thời gian chạy ngôn ngữ chung (CLR)
- Thư viện lớp .Net Framework
- Đặc điểm ngôn ngữ chung
- Hệ thống loại chung
- Siêu dữ liệu và tập hợp
- Biểu mẫu Windows
- ASP.Net và ASP.Net AJAX
- ADO.Net
- Windows Workflow Foundation (WF)
- Windows Presentation Foundation
- Windows Communication Foundation (WCF)
- LINQ
Để biết các công việc mà mỗi thành phần này thực hiện, vui lòng xem ASP.Net - Giới thiệu và để biết chi tiết của từng thành phần, vui lòng tham khảo tài liệu của Microsoft.
Môi trường phát triển tích hợp (IDE) cho C #
Microsoft cung cấp các công cụ phát triển sau để lập trình C #:
- Visual Studio 2010 (VS)
- Visual C # 2010 Express (VCE)
- Nhà phát triển Web trực quan
Hai bản cuối cùng được cung cấp miễn phí trên trang web chính thức của Microsoft. Sử dụng các công cụ này, bạn có thể viết tất cả các loại chương trình C # từ các ứng dụng dòng lệnh đơn giản đến các ứng dụng phức tạp hơn. Bạn cũng có thể viết các tệp mã nguồn C # bằng trình soạn thảo văn bản cơ bản, như Notepad và biên dịch mã thành các tập hợp bằng trình biên dịch dòng lệnh, trình biên dịch dòng lệnh này lại là một phần của .NET Framework.
Phiên bản Visual C # Express và Visual Web Developer Express là phiên bản rút gọn của Visual Studio và có cùng hình thức. Họ giữ lại hầu hết các tính năng của Visual Studio. Trong hướng dẫn này, chúng tôi đã sử dụng Visual C # 2010 Express.
Bạn có thể tải xuống từ Microsoft Visual Studio . Nó được cài đặt tự động trên máy của bạn.
Lưu ý: Bạn cần có kết nối internet hoạt động để cài đặt phiên bản nhanh.
Viết chương trình C # trên Linux hoặc Mac OS
Mặc dù .NET Framework chạy trên hệ điều hành Windows, nhưng có một số phiên bản thay thế hoạt động trên các hệ điều hành khác. Monolà phiên bản mã nguồn mở của .NET Framework bao gồm trình biên dịch C # và chạy trên một số hệ điều hành, bao gồm các phiên bản Linux và Mac OS khác nhau. Vui lòng kiểm tra Go Mono .
Mục đích đã nêu của Mono không chỉ là có thể chạy các ứng dụng Microsoft .NET đa nền tảng mà còn mang đến các công cụ phát triển tốt hơn cho các nhà phát triển Linux. Mono có thể chạy trên nhiều hệ điều hành bao gồm Android, BSD, iOS, Linux, OS X, Windows, Solaris và UNIX.
Trước khi nghiên cứu các khối xây dựng cơ bản của ngôn ngữ lập trình C #, chúng ta hãy xem cấu trúc chương trình C # tối thiểu để chúng ta có thể lấy nó làm tài liệu tham khảo trong các chương sắp tới.
Tạo chương trình Hello World
Chương trình AC # bao gồm các phần sau:
- Khai báo không gian tên
- Một lớp học
- Phương thức lớp
- Thuộc tính lớp
- Một phương pháp chính
- Tuyên bố và biểu thức
- Comments
Chúng ta hãy xem một đoạn mã đơn giản có in dòng chữ "Hello World" -
using System;
namespace HelloWorldApplication {
class HelloWorld {
static void Main(string[] args) {
/* my first program in C# */
Console.WriteLine("Hello World");
Console.ReadKey();
}
}
}
Khi mã này được biên dịch và thực thi, nó tạo ra kết quả sau:
Hello World
Chúng ta hãy xem xét các phần khác nhau của chương trình đã cho -
Dòng đầu tiên của chương trình using System; - các using từ khóa được sử dụng để bao gồm System không gian tên trong chương trình. Một chương trình thường có nhiềuusing các câu lệnh.
Dòng tiếp theo có namespacetờ khai. Anamespacelà một tập hợp các lớp. Không gian tên HelloWorldApplication chứa lớp HelloWorld .
Dòng tiếp theo có một classkhai báo, lớp HelloWorld chứa dữ liệu và định nghĩa phương thức mà chương trình của bạn sử dụng. Các lớp thường chứa nhiều phương thức. Các phương thức xác định hành vi của lớp. Tuy nhiên, lớp HelloWorld chỉ có một phương thức Main.
Dòng tiếp theo xác định Main phương pháp, đó là entry pointcho tất cả các chương trình C #. CácMain phương thức cho biết lớp sẽ làm gì khi được thực thi.
Dòng tiếp theo /*...*/ bị trình biên dịch bỏ qua và nó được thêm vào comments trong chương trình.
Phương thức Main chỉ định hành vi của nó với câu lệnh Console.WriteLine("Hello World");
WriteLine là một phương thức của lớp Console được định nghĩa trong không gian tên Hệ thống . Câu lệnh này gây ra thông báo "Hello, World!" được hiển thị trên màn hình.
Dòng cuối cùng Console.ReadKey();dành cho Người dùng VS.NET. Điều này làm cho chương trình chờ một lần nhấn phím và nó ngăn màn hình chạy và đóng nhanh khi chương trình được khởi chạy từ Visual Studio .NET.
Cần lưu ý những điểm sau:
- C # phân biệt chữ hoa chữ thường.
- Tất cả các câu lệnh và biểu thức phải kết thúc bằng dấu chấm phẩy (;).
- Việc thực thi chương trình bắt đầu tại phương thức Main.
- Không giống như Java, tên tệp chương trình có thể khác với tên lớp.
Biên dịch và Thực thi Chương trình
Nếu bạn đang sử dụng Visual Studio.Net để biên dịch và thực thi các chương trình C #, hãy thực hiện các bước sau:
Khởi động Visual Studio.
Trên thanh menu, chọn Tệp -> Mới -> Dự án.
Chọn Visual C # từ các mẫu, sau đó chọn Windows.
Chọn Ứng dụng Bảng điều khiển.
Chỉ định tên cho dự án của bạn và nhấp vào nút OK.
Điều này tạo ra một dự án mới trong Solution Explorer.
Viết mã trong Trình chỉnh sửa mã.
Nhấp vào nút Run hoặc nhấn phím F5 để thực hiện dự án. Một cửa sổ Command Prompt xuất hiện có dòng Hello World.
Bạn có thể biên dịch chương trình C # bằng cách sử dụng dòng lệnh thay vì Visual Studio IDE -
Mở trình soạn thảo văn bản và thêm mã được đề cập ở trên.
Lưu tệp dưới dạng helloworld.cs
Mở công cụ nhắc lệnh và chuyển đến thư mục bạn đã lưu tệp.
Kiểu csc helloworld.cs và nhấn enter để biên dịch mã của bạn.
Nếu không có lỗi nào trong mã của bạn, dấu nhắc lệnh sẽ đưa bạn đến dòng tiếp theo và tạo helloworld.exe tệp thực thi.
Kiểu helloworld để thực hiện chương trình của bạn.
Bạn có thể thấy đầu ra Hello World được in trên màn hình.
C # là một ngôn ngữ lập trình hướng đối tượng. Trong phương pháp lập trình hướng đối tượng, một chương trình bao gồm các đối tượng khác nhau tương tác với nhau bằng các hành động. Các hành động mà một đối tượng có thể thực hiện được gọi là các phương thức. Các đối tượng cùng loại được cho là có cùng loại hoặc, được cho là cùng lớp.
Ví dụ, chúng ta hãy xem xét một đối tượng Hình chữ nhật. Nó có các thuộc tính như chiều dài và chiều rộng. Tùy thuộc vào thiết kế, nó có thể cần các cách để chấp nhận các giá trị của các thuộc tính này, tính toán diện tích và hiển thị chi tiết.
Chúng ta hãy xem xét việc triển khai một lớp Rectangle và thảo luận về cú pháp cơ bản của C # -
using System;
namespace RectangleApplication {
class Rectangle {
// member variables
double length;
double width;
public void Acceptdetails() {
length = 4.5;
width = 3.5;
}
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.Acceptdetails();
r.Display();
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Length: 4.5
Width: 3.5
Area: 15.75
Việc sử dụng Từ khoá
Câu lệnh đầu tiên trong bất kỳ chương trình C # nào là
using System;
Các usingtừ khóa được sử dụng để bao gồm các không gian tên trong chương trình. Một chương trình có thể bao gồm nhiều câu lệnh using.
Các lớp học theo từ khóa
Các class từ khóa được sử dụng để khai báo một lớp.
Nhận xét trong C #
Nhận xét được sử dụng để giải thích mã. Trình biên dịch bỏ qua các mục nhận xét. Các chú thích nhiều dòng trong chương trình C # bắt đầu bằng / * và kết thúc bằng các ký tự * / như hình dưới đây -
/* This program demonstrates
The basic syntax of C# programming
Language */
Nhận xét một dòng được biểu thị bằng ký hiệu '//'. Ví dụ,
}//end class Rectangle
Biến thành viên
Biến là thuộc tính hoặc thành viên dữ liệu của một lớp, được sử dụng để lưu trữ dữ liệu. Trong chương trình trước, lớp Rectangle có hai biến thành viên có tên là chiều dài và chiều rộng .
Chức năng thành viên
Hàm là tập hợp các câu lệnh thực hiện một nhiệm vụ cụ thể. Các hàm thành viên của một lớp được khai báo trong lớp. Lớp mẫu Rectangle của chúng tôi chứa ba hàm thành viên: AcceptDetails , GetArea và Display .
Khởi tạo một lớp học
Trong chương trình trước, lớp ExecuteRectangle chứa phương thức Main () và khởi tạo lớp Rectangle .
Định danh
Định danh là tên được sử dụng để xác định một lớp, biến, hàm hoặc bất kỳ mục nào khác do người dùng xác định. Các quy tắc cơ bản để đặt tên các lớp trong C # như sau:
Tên phải bắt đầu bằng một chữ cái có thể được theo sau bởi một chuỗi các chữ cái, chữ số (0 - 9) hoặc dấu gạch dưới. Ký tự đầu tiên trong mã định danh không được là một chữ số.
Nó không được chứa bất kỳ không gian hoặc ký hiệu nhúng nào như? - +! @ #% ^ & * () [] {}. ; : "'/ và \. Tuy nhiên, có thể sử dụng dấu gạch dưới (_).
Nó không nên là một từ khóa C #.
Từ khóa C #
Từ khóa là những từ dành riêng được xác định trước cho trình biên dịch C #. Những từ khóa này không thể được sử dụng làm định danh. Tuy nhiên, nếu bạn muốn sử dụng các từ khóa này làm số nhận dạng, bạn có thể đặt tiền tố từ khóa bằng ký tự @.
Trong C #, một số định danh có ý nghĩa đặc biệt trong ngữ cảnh của mã, chẳng hạn như get và set được gọi là từ khóa theo ngữ cảnh.
Bảng sau liệt kê các từ khóa dành riêng và từ khóa theo ngữ cảnh trong C # -
Từ khóa dành riêng | ||||||
---|---|---|---|---|---|---|
trừu tượng | như | căn cứ | bool | phá vỡ | byte | trường hợp |
nắm lấy | char | đã kiểm tra | lớp học | hăng sô | tiếp tục | thập phân |
mặc định | ủy nhiệm | làm | gấp đôi | khác | enum | biến cố |
rõ ràng | bên ngoài | sai | cuối cùng | đã sửa | Phao nổi | cho |
cho mỗi | đi đến | nếu | ngầm hiểu | trong | trong (công cụ sửa đổi chung) | int |
giao diện | nội bộ | Là | Khóa | Dài | không gian tên | Mới |
vô giá trị | vật | nhà điều hành | ngoài | out (công cụ sửa đổi chung) | ghi đè | params |
riêng tư | được bảo vệ | công cộng | chỉ đọc | ref | trở về | sbyte |
niêm phong | ngắn | kích thước | stackalloc | tĩnh | chuỗi | cấu trúc |
công tắc điện | điều này | phi | thật | thử | loại | uint |
dài | không được kiểm tra | không an toàn | ushort | sử dụng | ảo | vô hiệu |
bay hơi | trong khi | |||||
Từ khóa theo ngữ cảnh | ||||||
thêm vào | bí danh | tăng dần | giảm dần | năng động | từ | được |
toàn cầu | nhóm | thành | tham gia | để cho | đặt bởi | một phần (loại) |
một phần (phương pháp) |
tẩy | lựa chọn | bộ |
Các biến trong C #, được phân loại thành các loại sau:
- Các loại giá trị
- Các loại tham chiếu
- Các loại con trỏ
Loại giá trị
Các biến kiểu giá trị có thể được gán giá trị trực tiếp. Chúng có nguồn gốc từ lớp System.ValueType.
Các loại giá trị trực tiếp chứa dữ liệu. Một số ví dụint, char, and float, nơi lưu trữ các số, bảng chữ cái và số dấu phẩy động, tương ứng. Khi bạn khai báo mộtint gõ, hệ thống cấp phát bộ nhớ để lưu giá trị.
Bảng sau liệt kê các kiểu giá trị có sẵn trong C # 2010 -
Kiểu | Đại diện | Phạm vi | Giá trị mặc định |
---|---|---|---|
bool | Giá trị boolean | Đúng hay sai | Sai |
byte | Số nguyên không dấu 8 bit | 0 đến 255 | 0 |
char | Ký tự Unicode 16 bit | U +0000 đến U + ffff | '\ 0' |
thập phân | Giá trị thập phân chính xác 128 bit với 28-29 chữ số có nghĩa | (-7,9 x 10 28 đến 7,9 x 10 28 ) / 10 0 đến 28 | 0,0 triệu |
gấp đôi | Loại dấu phẩy động chính xác kép 64 bit | (+/-) 5,0 x 10 -324 đến (+/-) 1,7 x 10 308 | 0.0D |
Phao nổi | Loại dấu phẩy động chính xác đơn 32 bit | -3,4 x 10 38 đến + 3,4 x 10 38 | 0,0F |
int | Kiểu số nguyên có dấu 32 bit | -2.147.483.648 đến 2.147.483.647 | 0 |
Dài | Loại số nguyên có dấu 64-bit | -9,223,372,036,854,775,808 đến 9,223,372,036,854,775,807 | 0L |
sbyte | Kiểu số nguyên có dấu 8 bit | -128 đến 127 | 0 |
ngắn | Kiểu số nguyên có dấu 16 bit | -32,768 đến 32,767 | 0 |
uint | Kiểu số nguyên không dấu 32 bit | 0 đến 4,294,967,295 | 0 |
dài | Kiểu số nguyên không dấu 64 bit | 0 đến 18.446.744.073.709.551.615 | 0 |
ushort | Kiểu số nguyên không dấu 16 bit | 0 đến 65,535 | 0 |
Để có được kích thước chính xác của một loại hoặc một biến trên một nền tảng cụ thể, bạn có thể sử dụng sizeofphương pháp. Biểu thức sizeof (type) mang lại kích thước lưu trữ của đối tượng hoặc kiểu tính bằng byte. Sau đây là một ví dụ để lấy kích thước của kiểu int trên bất kỳ máy nào:
using System;
namespace DataTypeApplication {
class Program {
static void Main(string[] args) {
Console.WriteLine("Size of int: {0}", sizeof(int));
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Size of int: 4
Loại tham chiếu
Các kiểu tham chiếu không chứa dữ liệu thực tế được lưu trữ trong một biến, nhưng chúng chứa một tham chiếu đến các biến.
Nói cách khác, chúng đề cập đến một vị trí bộ nhớ. Sử dụng nhiều biến, các kiểu tham chiếu có thể tham chiếu đến một vị trí bộ nhớ. Nếu dữ liệu trong vị trí bộ nhớ bị thay đổi bởi một trong các biến, thì biến kia sẽ tự động phản ánh sự thay đổi này về giá trị. Ví dụ củabuilt-in các loại tham chiếu là: object, dynamic, và string.
Loại đối tượng
Các Object Typelà lớp cơ sở cuối cùng cho tất cả các kiểu dữ liệu trong C # Common Type System (CTS). Đối tượng là một bí danh cho lớp System.Object. Các kiểu đối tượng có thể được gán giá trị của bất kỳ kiểu nào khác, kiểu giá trị, kiểu tham chiếu, kiểu được xác định trước hoặc do người dùng xác định. Tuy nhiên, trước khi gán giá trị, nó cần chuyển đổi kiểu.
Khi một kiểu giá trị được chuyển đổi thành kiểu đối tượng, nó được gọi là boxing và mặt khác, khi một kiểu đối tượng được chuyển đổi thành kiểu giá trị, nó được gọi là unboxing.
object obj;
obj = 100; // this is boxing
Loại động
Bạn có thể lưu trữ bất kỳ loại giá trị nào trong biến kiểu dữ liệu động. Việc kiểm tra kiểu cho các loại biến này diễn ra tại thời điểm chạy.
Cú pháp để khai báo một kiểu động là:
dynamic <variable_name> = value;
Ví dụ,
dynamic d = 20;
Kiểu động tương tự như kiểu đối tượng ngoại trừ việc kiểm tra kiểu đối với các biến kiểu đối tượng diễn ra tại thời điểm biên dịch, trong khi việc kiểm tra kiểu đối với các biến kiểu động diễn ra vào thời gian chạy.
Loại chuỗi
Các String Typecho phép bạn gán bất kỳ giá trị chuỗi nào cho một biến. Kiểu chuỗi là một bí danh cho lớp System.String. Nó có nguồn gốc từ kiểu đối tượng. Giá trị cho kiểu chuỗi có thể được gán bằng cách sử dụng các ký tự chuỗi ở hai dạng: được trích dẫn và @ được trích dẫn.
Ví dụ,
String str = "Tutorials Point";
Một chuỗi ký tự @ được trích dẫn trông như sau:
@"Tutorials Point";
Các kiểu tham chiếu do người dùng xác định là: lớp, giao diện hoặc đại biểu. Chúng ta sẽ thảo luận về các loại này trong chương sau.
Loại con trỏ
Các biến kiểu con trỏ lưu trữ địa chỉ bộ nhớ của kiểu khác. Con trỏ trong C # có cùng khả năng với con trỏ trong C hoặc C ++.
Cú pháp khai báo kiểu con trỏ là:
type* identifier;
Ví dụ,
char* cptr;
int* iptr;
Chúng ta sẽ thảo luận về các loại con trỏ trong chương 'Mã không an toàn'.
Chuyển đổi loại là chuyển đổi một loại dữ liệu sang một loại khác. Nó còn được gọi là Đúc kiểu. Trong C #, kiểu ép kiểu có hai dạng:
Implicit type conversion- Các chuyển đổi này được thực hiện bởi C # theo cách an toàn về loại. Ví dụ, là các chuyển đổi từ loại tích phân nhỏ hơn sang lớn hơn và chuyển đổi từ các lớp dẫn xuất sang các lớp cơ sở.
Explicit type conversion- Những chuyển đổi này được thực hiện một cách rõ ràng bởi người dùng sử dụng các chức năng được xác định trước. Chuyển đổi rõ ràng yêu cầu một toán tử truyền.
Ví dụ sau đây cho thấy một chuyển đổi loại rõ ràng -
using System;
namespace TypeConversionApplication {
class ExplicitConversion {
static void Main(string[] args) {
double d = 5673.74;
int i;
// cast double to int.
i = (int)d;
Console.WriteLine(i);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
5673
Phương pháp chuyển đổi loại C #
C # cung cấp các phương pháp chuyển đổi kiểu tích hợp sau:
Sr.No. | Phương pháp & Mô tả |
---|---|
1 | ToBoolean Chuyển đổi một kiểu thành giá trị Boolean, nếu có thể. |
2 | ToByte Chuyển đổi một loại thành một byte. |
3 | ToChar Chuyển đổi một loại thành một ký tự Unicode, nếu có thể. |
4 | ToDateTime Chuyển đổi một kiểu (kiểu số nguyên hoặc chuỗi) thành cấu trúc ngày-giờ. |
5 | ToDecimal Chuyển đổi một dấu phẩy động hoặc kiểu số nguyên thành kiểu thập phân. |
6 | ToDouble Chuyển đổi một loại thành một loại kép. |
7 | ToInt16 Chuyển đổi một kiểu thành số nguyên 16 bit. |
số 8 | ToInt32 Chuyển đổi một kiểu thành số nguyên 32 bit. |
9 | ToInt64 Chuyển đổi một kiểu thành số nguyên 64 bit. |
10 | ToSbyte Chuyển đổi một kiểu thành kiểu byte có dấu. |
11 | ToSingle Chuyển đổi một loại thành một số chấm động nhỏ. |
12 | ToString Chuyển đổi một kiểu thành một chuỗi. |
13 | ToType Chuyển đổi một loại thành một loại được chỉ định. |
14 | ToUInt16 Chuyển đổi một kiểu thành kiểu int không dấu. |
15 | ToUInt32 Chuyển đổi một loại thành một loại dài không dấu. |
16 | ToUInt64 Chuyển đổi một kiểu thành một số nguyên lớn không dấu. |
Ví dụ sau chuyển đổi các kiểu giá trị khác nhau thành kiểu chuỗi:
using System;
namespace TypeConversionApplication {
class StringConversion {
static void Main(string[] args) {
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;
Console.WriteLine(i.ToString());
Console.WriteLine(f.ToString());
Console.WriteLine(d.ToString());
Console.WriteLine(b.ToString());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
75
53.005
2345.7652
True
Một biến không là gì ngoài tên được đặt cho một vùng lưu trữ mà chương trình của chúng ta có thể thao tác. Mỗi biến trong C # có một kiểu cụ thể, xác định kích thước và cách bố trí bộ nhớ của biến, phạm vi giá trị có thể được lưu trong bộ nhớ đó và tập hợp các thao tác có thể áp dụng cho biến.
Các kiểu giá trị cơ bản được cung cấp trong C # có thể được phân loại là:
Kiểu | Thí dụ |
---|---|
Các loại tích phân | sbyte, byte, short, ushort, int, uint, long, ulong và char |
Các loại dấu chấm động | nổi và gấp đôi |
Các loại thập phân | thập phân |
Các kiểu boolean | giá trị đúng hoặc sai, như được chỉ định |
Loại vô hiệu | Kiểu dữ liệu vô hiệu |
C # cũng cho phép xác định các kiểu giá trị khác của biến như enum và các loại tham chiếu của các biến như class, mà chúng tôi sẽ đề cập trong các chương tiếp theo.
Xác định các biến
Cú pháp để định nghĩa biến trong C # là:
<data_type> <variable_list>;
Ở đây, data_type phải là kiểu dữ liệu C # hợp lệ bao gồm char, int, float, double, hoặc bất kỳ kiểu dữ liệu nào do người dùng xác định và biến_sách có thể bao gồm một hoặc nhiều tên định danh được phân tách bằng dấu phẩy.
Một số định nghĩa biến hợp lệ được hiển thị ở đây -
int i, j, k;
char c, ch;
float f, salary;
double d;
Bạn có thể khởi tạo một biến tại thời điểm định nghĩa là:
int i = 100;
Khởi tạo các biến
Các biến được khởi tạo (gán giá trị) bằng dấu bằng theo sau là biểu thức hằng số. Hình thức khởi tạo chung là -
variable_name = value;
Các biến có thể được khởi tạo trong phần khai báo của chúng. Bộ khởi tạo bao gồm một dấu bằng theo sau là một biểu thức hằng số là:
<data_type> <variable_name> = value;
Một số ví dụ là -
int d = 3, f = 5; /* initializing d and f. */
byte z = 22; /* initializes z. */
double pi = 3.14159; /* declares an approximation of pi. */
char x = 'x'; /* the variable x has the value 'x'. */
Thực hành lập trình tốt là khởi tạo các biến đúng cách, nếu không, đôi khi chương trình có thể tạo ra kết quả không mong muốn.
Ví dụ sau sử dụng nhiều loại biến khác nhau:
using System;
namespace VariableDefinition {
class Program {
static void Main(string[] args) {
short a;
int b ;
double c;
/* actual initialization */
a = 10;
b = 20;
c = a + b;
Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
a = 10, b = 20, c = 30
Chấp nhận giá trị từ người dùng
Các Console lớp học trong System không gian tên cung cấp một chức năng ReadLine() để chấp nhận đầu vào từ người dùng và lưu trữ nó vào một biến.
Ví dụ,
int num;
num = Convert.ToInt32(Console.ReadLine());
Chức năng Convert.ToInt32() chuyển đổi dữ liệu do người dùng nhập sang kiểu dữ liệu int, vì Console.ReadLine() chấp nhận dữ liệu ở định dạng chuỗi.
Biểu thức giá trị và giá trị trong C #
Có hai loại biểu thức trong C # -
lvalue - Một biểu thức là một giá trị có thể xuất hiện ở dạng bên trái hoặc bên phải của một phép gán.
rvalue - Một biểu thức là một giá trị có thể xuất hiện ở bên phải nhưng không xuất hiện ở bên trái của một phép gán.
Các biến là giá trị và do đó chúng có thể xuất hiện ở phía bên trái của phép gán. Các chữ số là các giá trị và do đó chúng có thể không được gán và không thể xuất hiện ở phía bên trái. Sau đây là một câu lệnh C # hợp lệ -
int g = 20;
Nhưng sau đây không phải là một câu lệnh hợp lệ và sẽ tạo ra lỗi thời gian biên dịch -
10 = 20;
Các hằng số tham chiếu đến các giá trị cố định mà chương trình không thể thay đổi trong quá trình thực thi. Các giá trị cố định này còn được gọi là các chữ. Hằng số có thể thuộc bất kỳ kiểu dữ liệu cơ bản nào như hằng số nguyên, hằng số động, hằng ký tự hoặc một chuỗi ký tự. Ngoài ra còn có các hằng số liệt kê.
Các hằng được xử lý giống như các biến thông thường ngoại trừ việc giá trị của chúng không thể được sửa đổi sau khi định nghĩa.
Chữ số nguyên
Một chữ số nguyên có thể là một hằng số thập phân hoặc thập lục phân. Tiền tố chỉ định cơ số hoặc cơ số: 0x hoặc 0X cho hệ thập lục phân và không có id tiền tố cho số thập phân.
Một chữ số nguyên cũng có thể có một hậu tố là sự kết hợp của U và L, tương ứng là không dấu và dài. Hậu tố có thể là chữ hoa hoặc chữ thường và có thể theo bất kỳ thứ tự nào.
Dưới đây là một số ví dụ về các ký tự số nguyên -
212 /* Legal */
215u /* Legal */
0xFeeL /* Legal */
Sau đây là các ví dụ khác về các loại ký tự Số nguyên khác nhau -
85 /* decimal */
0x4b /* hexadecimal */
30 /* int */
30u /* unsigned int */
30l /* long */
30ul /* unsigned long */
Chữ nổi dấu chấm động
Một ký tự dấu phẩy động có một phần nguyên, một dấu thập phân, một phần thập phân và một phần mũ. Bạn có thể biểu diễn các ký tự dấu phẩy động ở dạng thập phân hoặc dạng hàm mũ.
Dưới đây là một số ví dụ về các ký tự dấu phẩy động -
3.14159 /* Legal */
314159E-5F /* Legal */
510E /* Illegal: incomplete exponent */
210f /* Illegal: no decimal or exponent */
.e55 /* Illegal: missing integer or fraction */
Trong khi biểu diễn ở dạng thập phân, bạn phải bao gồm dấu thập phân, số mũ hoặc cả hai; và trong khi biểu diễn bằng cách sử dụng dạng mũ, bạn phải bao gồm phần nguyên, phần thập phân hoặc cả hai. Số mũ có dấu được giới thiệu bởi e hoặc E.
Hằng số ký tự
Các ký tự ký tự được đặt trong dấu ngoặc kép. Ví dụ, 'x' và có thể được lưu trữ trong một biến đơn giản kiểu char. Một chữ ký tự có thể là một ký tự thuần túy (chẳng hạn như 'x'), một chuỗi thoát (chẳng hạn như '\ t') hoặc một ký tự chung (chẳng hạn như '\ u02C0').
Có một số ký tự trong C # khi chúng đứng trước dấu gạch chéo ngược. Chúng có ý nghĩa đặc biệt và được dùng để biểu thị như dòng mới (\ n) hoặc tab (\ t). Đây là danh sách một số mã trình tự thoát như vậy -
Trình tự thoát | Ý nghĩa |
---|---|
\\ | \ tính cách |
\ ' | ' tính cách |
\ " | " tính cách |
\? | ? tính cách |
\ a | Cảnh báo hoặc chuông |
\ b | Backspace |
\ f | Thức ăn dạng |
\ n | Dòng mới |
\ r | Vận chuyển trở lại |
\ t | Tab ngang |
\ v | Tab dọc |
\ xhh. . . | Số thập lục phân gồm một hoặc nhiều chữ số |
Dưới đây là ví dụ để hiển thị một số ký tự thoát -
using System;
namespace EscapeChar {
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello\tWorld\n\n");
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Hello World
Chuỗi chữ
Các ký tự hoặc hằng số của chuỗi được đặt trong dấu ngoặc kép "" hoặc với @ "". Một chuỗi chứa các ký tự tương tự như các ký tự: ký tự thuần túy, chuỗi thoát và ký tự phổ quát.
Bạn có thể ngắt một dòng dài thành nhiều dòng bằng cách sử dụng các ký tự chuỗi và phân tách các phần bằng cách sử dụng khoảng trắng.
Dưới đây là một số ví dụ về chuỗi ký tự. Tất cả ba hình thức là các chuỗi giống hệt nhau.
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
@"hello dear"
Định nghĩa Hằng số
Hằng số được xác định bằng cách sử dụng consttừ khóa. Cú pháp để xác định một hằng số là:
const <data_type> <constant_name> = value;
Chương trình sau minh họa việc xác định và sử dụng một hằng số trong chương trình của bạn:
using System;
namespace DeclaringConstants {
class Program {
static void Main(string[] args) {
const double pi = 3.14159;
// constant declaration
double r;
Console.WriteLine("Enter Radius: ");
r = Convert.ToDouble(Console.ReadLine());
double areaCircle = pi * r * r;
Console.WriteLine("Radius: {0}, Area: {1}", r, areaCircle);
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Enter Radius:
3
Radius: 3, Area: 28.27431
Một toán tử là một ký hiệu yêu cầu trình biên dịch thực hiện các thao tác toán học hoặc logic cụ thể. C # có nhiều toán tử tích hợp sẵn và cung cấp các loại toán tử sau:
- Toán tử số học
- Toán tử quan hệ
- Toán tử logic
- Toán tử Bitwise
- Người điều hành nhiệm vụ
- Nhà điều hành khác
Hướng dẫn này giải thích từng toán tử số học, quan hệ, logic, bitwise, phép gán và các toán tử khác.
Toán tử số học
Bảng sau hiển thị tất cả các toán tử số học được hỗ trợ bởi C #. Giả sử biếnA giữ 10 và biến B giữ 20 sau đó -
Hiển thị các ví dụ
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
+ | Thêm hai toán hạng | A + B = 30 |
- | Trừ toán hạng thứ hai với toán hạng đầu tiên | A - B = -10 |
* | Nhân cả hai toán hạng | A * B = 200 |
/ | Chia tử số cho tử số | B / A = 2 |
% | Toán tử mô đun và phần còn lại của sau một phép chia số nguyên | B% A = 0 |
++ | Toán tử tăng dần làm tăng giá trị số nguyên lên một | A ++ = 11 |
- | Toán tử giảm dần giảm giá trị số nguyên đi một | A-- = 9 |
Toán tử quan hệ
Bảng sau đây cho thấy tất cả các toán tử quan hệ được hỗ trợ bởi C #. Giả sử biếnA giữ 10 và biến B giữ 20, sau đó -
Hiển thị các ví dụ
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
== | Kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không, nếu có thì điều kiện trở thành true. | (A == B) không đúng. |
! = | Kiểm tra xem giá trị của hai toán hạng có bằng nhau hay không, nếu các giá trị không bằng nhau thì điều kiện trở thành true. | (A! = B) là đúng. |
> | Kiểm tra xem giá trị của toán hạng bên trái có lớn hơn giá trị của toán hạng bên phải hay không, nếu có thì điều kiện trở thành true. | (A> B) là không đúng. |
< | Kiểm tra xem giá trị của toán hạng bên trái có nhỏ hơn giá trị của toán hạng bên phải hay không, nếu có thì điều kiện trở thành true. | (A <B) là đúng. |
> = | Kiểm tra xem giá trị của toán hạng bên trái có lớn hơn hoặc bằng giá trị của toán hạng bên phải hay không, nếu có thì điều kiện trở thành true. | (A> = B) là không đúng. |
<= | Kiểm tra xem giá trị của toán hạng bên trái có nhỏ hơn hoặc bằng giá trị của toán hạng bên phải hay không, nếu có thì điều kiện trở thành true. | (A <= B) là đúng. |
Toán tử logic
Bảng sau đây hiển thị tất cả các toán tử logic được hỗ trợ bởi C #. Giả sử biếnA giữ giá trị Boolean true và biến B giữ giá trị Boolean false, sau đó -
Hiển thị các ví dụ
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
&& | Được gọi là toán tử logic AND. Nếu cả hai toán hạng đều khác 0 thì điều kiện trở thành true. | (A && B) là sai. |
|| | Được gọi là Toán tử logic HOẶC. Nếu bất kỳ toán hạng nào trong hai toán hạng khác 0 thì điều kiện trở thành true. | (A || B) là đúng. |
! | Được gọi là Toán tử logic NOT. Sử dụng để đảo ngược trạng thái logic của toán hạng của nó. Nếu một điều kiện là đúng thì toán tử logic NOT sẽ sai. | ! (A && B) là đúng. |
Toán tử Bitwise
Toán tử bitwise hoạt động trên các bit và thực hiện thao tác từng bit. Bảng sự thật cho &, |, và ^ như sau:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Giả sử nếu A = 60; và B = 13; thì ở định dạng nhị phân, chúng như sau:
A = 0011 1100
B = 0000 1101
-------------------
A&B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~ A = 1100 0011
Các toán tử Bitwise được C # hỗ trợ được liệt kê trong bảng sau. Giả sử biến A giữ 60 và biến B giữ 13, thì -
Hiển thị các ví dụ
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
& | Toán tử AND nhị phân sao chép một bit vào kết quả nếu nó tồn tại trong cả hai toán hạng. | (A & B) = 12, là 0000 1100 |
| | Toán tử OR nhị phân sao chép một bit nếu nó tồn tại trong một trong hai toán hạng. | (A | B) = 61, là 0011 1101 |
^ | Toán tử XOR nhị phân sao chép bit nếu nó được đặt trong một toán hạng nhưng không phải cả hai. | (A ^ B) = 49, là 0011 0001 |
~ | Toán tử bổ sung số nhị phân là một ngôi và có tác dụng 'lật' các bit. | (~ A) = -61, là 1100 0011 trong phần bù của 2 do một số nhị phân có dấu. |
<< | Toán tử dịch chuyển trái nhị phân. Giá trị toán hạng bên trái được di chuyển sang trái bằng số bit được chỉ định bởi toán hạng bên phải. | A << 2 = 240, là 1111 0000 |
>> | Toán tử Shift phải nhị phân. Giá trị của toán hạng bên trái được di chuyển sang phải bằng số bit được chỉ định bởi toán hạng bên phải. | A >> 2 = 15, là 0000 1111 |
Người điều hành nhiệm vụ
Có các toán tử gán sau được C # hỗ trợ:
Hiển thị các ví dụ
Nhà điều hành | Sự miêu tả | Thí dụ |
---|---|---|
= | Toán tử gán đơn giản, Gán giá trị từ toán hạng bên phải sang toán hạng bên trái | C = A + B gán giá trị của A + B vào C |
+ = | Thêm toán tử gán AND, Nó thêm toán hạng bên phải vào toán hạng bên trái và gán kết quả cho toán hạng bên trái | C + = A tương đương với C = C + A |
- = | Trừ toán tử gán AND, Nó trừ toán hạng bên phải khỏi toán hạng bên trái và gán kết quả cho toán hạng bên trái | C - = A tương đương với C = C - A |
* = | Nhân toán tử gán AND, Nó nhân toán hạng phải với toán hạng trái và gán kết quả cho toán hạng trái | C * = A tương đương với C = C * A |
/ = | Toán tử gán AND, Nó chia toán hạng bên trái với toán hạng bên phải và gán kết quả cho toán hạng bên trái | C / = A tương đương với C = C / A |
% = | Toán tử gán mô-đun AND, cần mô-đun sử dụng hai toán hạng và gán kết quả cho toán hạng bên trái | C% = A tương đương với C = C% A |
<< = | Dịch chuyển trái và toán tử gán | C << = 2 giống với C = C << 2 |
>> = | Toán tử chuyển nhượng AND phải | C >> = 2 giống với C = C >> 2 |
& = | Toán tử gán bitwise AND | C & = 2 giống C = C & 2 |
^= | bitwise exclusive OR and assignment operator | C ^= 2 is same as C = C ^ 2 |
|= | bitwise inclusive OR and assignment operator | C |= 2 is same as C = C | 2 |
Miscellaneous Operators
There are few other important operators including sizeof, typeof and ? : supported by C#.
Show Examples
Operator | Description | Example |
---|---|---|
sizeof() | Returns the size of a data type. | sizeof(int), returns 4. |
typeof() | Returns the type of a class. | typeof(StreamReader); |
& | Returns the address of an variable. | &a; returns actual address of the variable. |
* | Pointer to a variable. | *a; creates pointer named 'a' to a variable. |
? : | Conditional Expression | If Condition is true ? Then value X : Otherwise value Y |
is | Determines whether an object is of a certain type. | If( Ford is Car) // checks if Ford is an object of the Car class. |
as | Cast without raising an exception if the cast fails. | Object obj = new StringReader("Hello"); StringReader r = obj as StringReader; |
Operator Precedence in C#
Operator precedence determines the grouping of terms in an expression. This affects evaluation of an expression. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.
For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so the first evaluation takes place for 3*2 and then 7 is added into it.
Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators are evaluated first.
Show Examples
Category | Operator | Associativity |
---|---|---|
Postfix | () [] -> . ++ - - | Left to right |
Unary | + - ! ~ ++ - - (type)* & sizeof | Right to left |
Multiplicative | * / % | Left to right |
Additive | + - | Left to right |
Shift | << >> | Left to right |
Relational | < <= > >= | Left to right |
Equality | == != | Left to right |
Bitwise AND | & | Left to right |
Bitwise XOR | ^ | Left to right |
Bitwise OR | | | Left to right |
Logical AND | && | Left to right |
Logical OR | || | Left to right |
Conditional | ?: | Right to left |
Assignment | = += -= *= /= %=>>= <<= &= ^= |= | Right to left |
Comma | , | Left to right |
Decision making structures requires the programmer to specify one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.
Following is the general form of a typical decision making structure found in most of the programming languages −
C# provides following types of decision making statements. Click the following links to check their detail.
Sr.No. | Statement & Description |
---|---|
1 | if statement An if statement consists of a boolean expression followed by one or more statements. |
2 | if...else statement An if statement can be followed by an optional else statement, which executes when the boolean expression is false. |
3 | nested if statements You can use one if or else if statement inside another if or else if statement(s). |
4 | switch statement A switch statement allows a variable to be tested for equality against a list of values. |
5 | nested switch statements You can use one switch statement inside another switch statement(s). |
The ? : Operator
We have covered conditional operator ? : in previous chapter which can be used to replace if...else statements. It has the following general form −
Exp1 ? Exp2 : Exp3;
Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ? expression is determined as follows: Exp1 is evaluated. If it is true, then Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is evaluated and its value becomes the value of the expression.
There may be a situation, when you need to execute a block of code several number of times. In general, the statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.
Programming languages provide various control structures that allow for more complicated execution paths.
A loop statement allows us to execute a statement or a group of statements multiple times and following is the general from of a loop statement in most of the programming languages −
C# provides following types of loop to handle looping requirements. Click the following links to check their detail.
Sr.No. | Loop Type & Description |
---|---|
1 | while loop It repeats a statement or a group of statements while a given condition is true. It tests the condition before executing the loop body. |
2 | for loop It executes a sequence of statements multiple times and abbreviates the code that manages the loop variable. |
3 | do...while loop It is similar to a while statement, except that it tests the condition at the end of the loop body |
4 | nested loops You can use one or more loop inside any another while, for or do..while loop. |
Loop Control Statements
Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.
C# provides the following control statements. Click the following links to check their details.
Sr.No. | Control Statement & Description |
---|---|
1 | break statement Terminates the loop or switch statement and transfers execution to the statement immediately following the loop or switch. |
2 | continue statement Causes the loop to skip the remainder of its body and immediately retest its condition prior to reiterating. |
Infinite Loop
A loop becomes infinite loop if a condition never becomes false. The for loop is traditionally used for this purpose. Since none of the three expressions that form the for loop are required, you can make an endless loop by leaving the conditional expression empty.
Example
using System;
namespace Loops {
class Program {
static void Main(string[] args) {
for (; ; ) {
Console.WriteLine("Hey! I am Trapped");
}
}
}
}
When the conditional expression is absent, it is assumed to be true. You may have an initialization and increment expression, but programmers more commonly use the for(;;) construct to signify an infinite loop.
Encapsulationđược định nghĩa 'là quá trình bao bọc một hoặc nhiều mục trong một gói vật lý hoặc lôgic'. Đóng gói, trong phương pháp luận lập trình hướng đối tượng, ngăn cản quyền truy cập vào các chi tiết triển khai.
Tính trừu tượng và tính đóng gói là các tính năng liên quan trong lập trình hướng đối tượng. Tính trừu tượng cho phép hiển thị thông tin liên quan và tính đóng gói cho phép lập trình viên thực hiện mức độ trừu tượng mong muốn .
Đóng gói được thực hiện bằng cách sử dụng access specifiers. Anaccess specifierxác định phạm vi và khả năng hiển thị của một thành viên trong lớp. C # hỗ trợ các chỉ định truy cập sau:
- Public
- Private
- Protected
- Internal
- Được bảo vệ bên trong
Công cụ xác định quyền truy cập công khai
Bộ chỉ định truy cập công khai cho phép một lớp hiển thị các biến thành viên và các hàm thành viên của nó với các hàm và đối tượng khác. Mọi thành viên công cộng có thể được truy cập từ bên ngoài lớp.
Ví dụ sau minh họa điều này -
using System;
namespace RectangleApplication {
class Rectangle {
//member variables
public double length;
public double width;
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Length: 4.5
Width: 3.5
Area: 15.75
Trong ví dụ trước, các biến thành viên chiều dài và chiều rộng được khai báo public, vì vậy chúng có thể được truy cập từ hàm Main () bằng cách sử dụng một thể hiện của lớp Rectangle, có tên r.
Hàm thành viên Display () và GetArea () cũng có thể truy cập trực tiếp các biến này mà không cần sử dụng bất kỳ thể hiện nào của lớp.
Các hàm thành viên Display () cũng được khai báopublic, vì vậy nó cũng có thể được truy cập từ Main () bằng cách sử dụng một thể hiện của lớp Rectangle, có tênr.
Bộ định danh quyền truy cập riêng tư
Bộ xác định quyền truy cập riêng tư cho phép một lớp ẩn các biến thành viên và các hàm thành viên của nó khỏi các hàm và đối tượng khác. Chỉ các hàm của cùng một lớp mới có thể truy cập các thành viên riêng của nó. Ngay cả một thể hiện của một lớp cũng không thể truy cập các thành viên riêng tư của nó.
Ví dụ sau minh họa điều này -
using System;
namespace RectangleApplication {
class Rectangle {
//member variables
private double length;
private double width;
public void Acceptdetails() {
Console.WriteLine("Enter Length: ");
length = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Enter Width: ");
width = Convert.ToDouble(Console.ReadLine());
}
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.Acceptdetails();
r.Display();
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Enter Length:
4.4
Enter Width:
3.3
Length: 4.4
Width: 3.3
Area: 14.52
Trong ví dụ trước, các biến thành viên chiều dài và chiều rộng được khai báo private, vì vậy chúng không thể được truy cập từ hàm Main (). Các hàm thành viên AcceptDetails () và Display () có thể truy cập các biến này. Vì các hàm thành viên AcceptDetails () và Display () được khai báopublic, chúng có thể được truy cập từ Main () bằng cách sử dụng một thể hiện của lớp Rectangle, có tênr.
Bộ chỉ định quyền truy cập được bảo vệ
Bộ chỉ định truy cập được bảo vệ cho phép một lớp con truy cập các biến thành viên và các hàm thành viên của lớp cơ sở của nó. Bằng cách này nó sẽ giúp thực hiện kế thừa. Chúng ta sẽ thảo luận chi tiết hơn về vấn đề này trong chương kế thừa.
Thông số truy cập nội bộ
Bộ chỉ định truy cập nội bộ cho phép một lớp hiển thị các biến thành viên và hàm thành viên của nó với các hàm và đối tượng khác trong hợp ngữ hiện tại. Nói cách khác, bất kỳ thành viên nào có chỉ định truy cập nội bộ đều có thể được truy cập từ bất kỳ lớp hoặc phương thức nào được xác định trong ứng dụng mà thành viên đó được xác định.
Chương trình sau đây minh họa điều này -
using System;
namespace RectangleApplication {
class Rectangle {
//member variables
internal double length;
internal double width;
double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Length: 4.5
Width: 3.5
Area: 15.75
Trong ví dụ trước, lưu ý rằng hàm thành viên GetArea () không được khai báo với bất kỳ mã xác định quyền truy cập nào. Sau đó, chỉ định truy cập mặc định của một thành viên trong lớp sẽ là gì nếu chúng ta không đề cập đến bất kỳ? Nó làprivate.
Bộ chỉ định quyền truy cập nội bộ được bảo vệ
Bộ chỉ định quyền truy cập nội bộ được bảo vệ cho phép một lớp ẩn các biến thành viên và hàm thành viên của nó khỏi các đối tượng và chức năng của lớp khác, ngoại trừ một lớp con trong cùng một ứng dụng. Điều này cũng được sử dụng trong khi thực hiện kế thừa.
Phương thức là một nhóm các câu lệnh cùng thực hiện một tác vụ. Mỗi chương trình C # đều có ít nhất một lớp với một phương thức có tên là Main.
Để sử dụng một phương pháp, bạn cần phải -
- Xác định phương pháp
- Gọi phương thức
Định nghĩa các phương thức trong C #
Khi bạn định nghĩa một phương thức, về cơ bản bạn khai báo các phần tử trong cấu trúc của nó. Cú pháp để xác định một phương thức trong C # như sau:
<Access Specifier> <Return Type> <Method Name>(Parameter List) {
Method Body
}
Sau đây là các yếu tố khác nhau của một phương thức:
Access Specifier - Điều này xác định khả năng hiển thị của một biến hoặc một phương thức từ một lớp khác.
Return type- Một phương thức có thể trả về một giá trị. Kiểu trả về là kiểu dữ liệu của giá trị mà phương thức trả về. Nếu phương thức không trả về bất kỳ giá trị nào, thì kiểu trả về làvoid.
Method name- Tên phương thức là một định danh duy nhất và nó có phân biệt chữ hoa chữ thường. Nó không thể giống với bất kỳ định danh nào khác được khai báo trong lớp.
Parameter list- Được bao giữa các dấu ngoặc, các tham số được sử dụng để truyền và nhận dữ liệu từ một phương thức. Danh sách tham số đề cập đến kiểu, thứ tự và số lượng các tham số của một phương thức. Các thông số là tùy chọn; nghĩa là, một phương thức có thể không chứa tham số.
Method body - Điều này chứa tập hợp các hướng dẫn cần thiết để hoàn thành hoạt động được yêu cầu.
Thí dụ
Đoạn mã sau đây cho thấy một hàm FindMax nhận hai giá trị nguyên và trả về giá trị lớn hơn trong hai giá trị đó. Nó có chỉ định truy cập công khai, vì vậy nó có thể được truy cập từ bên ngoài lớp bằng cách sử dụng một thể hiện của lớp.
class NumberManipulator {
public int FindMax(int num1, int num2) {
/* local variable declaration */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
...
}
Phương thức gọi trong C #
Bạn có thể gọi một phương thức bằng cách sử dụng tên của phương thức đó. Ví dụ sau minh họa điều này -
using System;
namespace CalculatorApplication {
class NumberManipulator {
public int FindMax(int num1, int num2) {
/* local variable declaration */
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
static void Main(string[] args) {
/* local variable definition */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//calling the FindMax method
ret = n.FindMax(a, b);
Console.WriteLine("Max value is : {0}", ret );
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Max value is : 200
Bạn cũng có thể gọi phương thức công khai từ các lớp khác bằng cách sử dụng thể hiện của lớp. Ví dụ, phương thức FindMax thuộc lớp NumberManipulator , bạn có thể gọi nó từ Test lớp khác .
using System;
namespace CalculatorApplication {
class NumberManipulator {
public int FindMax(int num1, int num2) {
/* local variable declaration */
int result;
if(num1 > num2)
result = num1;
else
result = num2;
return result;
}
}
class Test {
static void Main(string[] args) {
/* local variable definition */
int a = 100;
int b = 200;
int ret;
NumberManipulator n = new NumberManipulator();
//calling the FindMax method
ret = n.FindMax(a, b);
Console.WriteLine("Max value is : {0}", ret );
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Max value is : 200
Cuộc gọi phương thức đệ quy
Một phương thức có thể gọi chính nó. Điều này được gọi làrecursion. Sau đây là một ví dụ tính toán giai thừa cho một số nhất định bằng cách sử dụng một hàm đệ quy:
using System;
namespace CalculatorApplication {
class NumberManipulator {
public int factorial(int num) {
/* local variable declaration */
int result;
if (num == 1) {
return 1;
}
else {
result = factorial(num - 1) * num;
return result;
}
}
static void Main(string[] args) {
NumberManipulator n = new NumberManipulator();
//calling the factorial method {0}", n.factorial(6));
Console.WriteLine("Factorial of 7 is : {0}", n.factorial(7));
Console.WriteLine("Factorial of 8 is : {0}", n.factorial(8));
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Factorial of 6 is: 720
Factorial of 7 is: 5040
Factorial of 8 is: 40320
Chuyển các tham số cho một phương pháp
Khi phương thức có tham số được gọi, bạn cần truyền các tham số cho phương thức. Có ba cách mà các tham số có thể được truyền cho một phương thức:
Sr.No. | Cơ chế & Mô tả |
---|---|
1 | Tham số giá trị Phương thức này sao chép giá trị thực của một đối số vào tham số chính thức của hàm. Trong trường hợp này, các thay đổi được thực hiện đối với tham số bên trong hàm không ảnh hưởng đến đối số. |
2 | Thông số tham khảo Phương thức này sao chép tham chiếu đến vị trí bộ nhớ của một đối số vào tham số chính thức. Điều này có nghĩa là các thay đổi được thực hiện đối với tham số sẽ ảnh hưởng đến đối số. |
3 | Thông số đầu ra Phương thức này giúp trả về nhiều giá trị. |
C # cung cấp một kiểu dữ liệu đặc biệt, nullable loại, mà bạn có thể gán phạm vi giá trị bình thường cũng như giá trị null.
Ví dụ: bạn có thể lưu trữ bất kỳ giá trị nào từ -2,147,483,648 đến 2,147,483,647 hoặc null trong biến Nullable <Int32>. Tương tự, bạn có thể gán true, false hoặc null trong biến Nullable <bool>. Cú pháp khai báonullable loại như sau -
< data_type> ? <variable_name> = null;
Ví dụ sau minh họa việc sử dụng kiểu dữ liệu nullable:
using System;
namespace CalculatorApplication {
class NullablesAtShow {
static void Main(string[] args) {
int? num1 = null;
int? num2 = 45;
double? num3 = new double?();
double? num4 = 3.14157;
bool? boolval = new bool?();
// display the values
Console.WriteLine("Nullables at Show: {0}, {1}, {2}, {3}", num1, num2, num3, num4);
Console.WriteLine("A Nullable boolean value: {0}", boolval);
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Nullables at Show: , 45, , 3.14157
A Nullable boolean value:
Nhà điều hành Null Coalescing (??)
Toán tử kết hợp null được sử dụng với các kiểu giá trị và kiểu tham chiếu có thể null. Nó được sử dụng để chuyển đổi một toán hạng sang kiểu của một toán hạng kiểu giá trị nullable (hoặc không) khác, nơi có thể thực hiện chuyển đổi ngầm định.
Nếu giá trị của toán hạng đầu tiên là null, thì toán tử trả về giá trị của toán hạng thứ hai, ngược lại nó trả về giá trị của toán hạng đầu tiên. Ví dụ sau giải thích điều này -
using System;
namespace CalculatorApplication {
class NullablesAtShow {
static void Main(string[] args) {
double? num1 = null;
double? num2 = 3.14157;
double num3;
num3 = num1 ?? 5.34;
Console.WriteLine(" Value of num3: {0}", num3);
num3 = num2 ?? 5.34;
Console.WriteLine(" Value of num3: {0}", num3);
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of num3: 5.34
Value of num3: 3.14157
Một mảng lưu trữ một tập hợp tuần tự có kích thước cố định của các phần tử cùng kiểu. Mảng được sử dụng để lưu trữ một tập hợp dữ liệu, nhưng thường hữu ích hơn nếu coi mảng như một tập hợp các biến cùng kiểu được lưu trữ tại các vị trí bộ nhớ liền kề.
Thay vì khai báo các biến riêng lẻ, chẳng hạn như number0, number1, ... và number99, bạn khai báo một biến mảng chẳng hạn như số và sử dụng số [0], số [1] và ..., số [99] để biểu diễn các biến riêng lẻ. Một phần tử cụ thể trong một mảng được truy cập bởi một chỉ mục.
Tất cả các mảng bao gồm các vị trí bộ nhớ liền nhau. Địa chỉ thấp nhất tương ứng với phần tử đầu tiên và địa chỉ cao nhất cho phần tử cuối cùng.
Khai báo Mảng
Để khai báo một mảng trong C #, bạn có thể sử dụng cú pháp sau:
datatype[] arrayName;
Ở đâu,
datatype được sử dụng để chỉ định loại phần tử trong mảng.
[] xác định thứ hạng của mảng. Xếp hạng xác định kích thước của mảng.
arrayName chỉ định tên của mảng.
Ví dụ,
double[] balance;
Khởi tạo một mảng
Khai báo mảng không khởi tạo mảng trong bộ nhớ. Khi biến mảng được khởi tạo, bạn có thể gán giá trị cho mảng.
Mảng là một kiểu tham chiếu, vì vậy bạn cần sử dụng newtừ khóa để tạo một thể hiện của mảng. Ví dụ,
double[] balance = new double[10];
Gán giá trị cho một mảng
Bạn có thể gán giá trị cho các phần tử mảng riêng lẻ, bằng cách sử dụng số chỉ mục, như -
double[] balance = new double[10];
balance[0] = 4500.0;
Bạn có thể gán các giá trị cho mảng tại thời điểm khai báo, như minh họa:
double[] balance = { 2340.0, 4523.69, 3421.0};
Bạn cũng có thể tạo và khởi tạo một mảng, như minh họa:
int [] marks = new int[5] { 99, 98, 92, 97, 95};
Bạn cũng có thể bỏ qua kích thước của mảng, như được hiển thị:
int [] marks = new int[] { 99, 98, 92, 97, 95};
Bạn có thể sao chép một biến mảng vào một biến mảng đích khác. Trong trường hợp đó, cả đích và nguồn đều trỏ đến cùng một vị trí bộ nhớ -
int [] marks = new int[] { 99, 98, 92, 97, 95};
int[] score = marks;
Khi bạn tạo một mảng, trình biên dịch C # khởi tạo ngầm định mỗi phần tử mảng thành một giá trị mặc định tùy thuộc vào kiểu mảng. Ví dụ, đối với một mảng int, tất cả các phần tử được khởi tạo bằng 0.
Truy cập các phần tử mảng
Một phần tử được truy cập bằng cách đánh chỉ mục tên mảng. Điều này được thực hiện bằng cách đặt chỉ mục của phần tử trong dấu ngoặc vuông sau tên của mảng. Ví dụ,
double salary = balance[9];
Ví dụ sau đây, minh họa cho việc khai báo, gán và truy cập các mảng khái niệm được đề cập ở trên -
using System;
namespace ArrayApplication {
class MyArray {
static void Main(string[] args) {
int [] n = new int[10]; /* n is an array of 10 integers */
int i,j;
/* initialize elements of array n */
for ( i = 0; i < 10; i++ ) {
n[ i ] = i + 100;
}
/* output each array element's value */
for (j = 0; j < 10; j++ ) {
Console.WriteLine("Element[{0}] = {1}", j, n[j]);
}
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Sử dụng vòng lặp foreach
Trong ví dụ trước, chúng ta đã sử dụng vòng lặp for để truy cập từng phần tử mảng. Bạn cũng có thể sử dụngforeach câu lệnh lặp qua một mảng.
using System;
namespace ArrayApplication {
class MyArray {
static void Main(string[] args) {
int [] n = new int[10]; /* n is an array of 10 integers */
/* initialize elements of array n */
for ( int i = 0; i < 10; i++ ) {
n[i] = i + 100;
}
/* output each array element's value */
foreach (int j in n ) {
int i = j-100;
Console.WriteLine("Element[{0}] = {1}", i, j);
}
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
Mảng C #
Có một vài khái niệm quan trọng sau đây liên quan đến mảng mà một lập trình viên C # phải rõ ràng:
Sr.No. | Khái niệm & Mô tả |
---|---|
1 | Mảng đa chiều C # hỗ trợ mảng nhiều chiều. Dạng đơn giản nhất của mảng nhiều chiều là mảng hai chiều. |
2 | Mảng răng cưa C # hỗ trợ mảng nhiều chiều, là mảng của mảng. |
3 | Truyền mảng cho các hàm Bạn có thể chuyển cho hàm một con trỏ tới một mảng bằng cách chỉ định tên của mảng mà không có chỉ mục. |
4 | Mảng tham số Điều này được sử dụng để truyền số lượng tham số chưa biết cho một hàm. |
5 | Lớp mảng Được định nghĩa trong không gian tên Hệ thống, nó là lớp cơ sở cho tất cả các mảng và cung cấp các thuộc tính và phương thức khác nhau để làm việc với mảng. |
Trong C #, bạn có thể sử dụng chuỗi dưới dạng mảng ký tự, Tuy nhiên, thực tiễn phổ biến hơn là sử dụng stringtừ khóa để khai báo một biến chuỗi. Từ khóa chuỗi là một bí danh choSystem.String lớp học.
Tạo một đối tượng chuỗi
Bạn có thể tạo đối tượng chuỗi bằng một trong các phương pháp sau:
Bằng cách gán một chuỗi ký tự cho một biến Chuỗi
Bằng cách sử dụng phương thức khởi tạo lớp String
Bằng cách sử dụng toán tử nối chuỗi (+)
Bằng cách truy xuất một thuộc tính hoặc gọi một phương thức trả về một chuỗi
Bằng cách gọi một phương thức định dạng để chuyển đổi một giá trị hoặc một đối tượng thành biểu diễn chuỗi của nó
Ví dụ sau đây chứng minh điều này -
using System;
namespace StringApplication {
class Program {
static void Main(string[] args) {
//from string literal and string concatenation
string fname, lname;
fname = "Rowan";
lname = "Atkinson";
char []letters= { 'H', 'e', 'l', 'l','o' };
string [] sarray={ "Hello", "From", "Tutorials", "Point" };
string fullname = fname + lname;
Console.WriteLine("Full Name: {0}", fullname);
//by using string constructor { 'H', 'e', 'l', 'l','o' };
string greetings = new string(letters);
Console.WriteLine("Greetings: {0}", greetings);
//methods returning string { "Hello", "From", "Tutorials", "Point" };
string message = String.Join(" ", sarray);
Console.WriteLine("Message: {0}", message);
//formatting method to convert a value
DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1);
string chat = String.Format("Message sent at {0:t} on {0:D}", waiting);
Console.WriteLine("Message: {0}", chat);
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Full Name: RowanAtkinson
Greetings: Hello
Message: Hello From Tutorials Point
Message: Message sent at 5:58 PM on Wednesday, October 10, 2012
Thuộc tính của lớp chuỗi
Lớp String có hai thuộc tính sau:
Sr.No. | Kê khai tài sản |
---|---|
1 | Chars Gets the Char đối tượng tại một vị trí xác định trong hiện tại chuỗi đối tượng. |
2 | Length Nhận số ký tự trong đối tượng Chuỗi hiện tại. |
Các phương thức của lớp chuỗi
Lớp String có nhiều phương thức giúp bạn làm việc với các đối tượng chuỗi. Bảng sau cung cấp một số phương pháp được sử dụng phổ biến nhất:
Sr.No. | Phương pháp & Mô tả |
---|---|
1 | public static int Compare(string strA, string strB) So sánh hai đối tượng chuỗi được chỉ định và trả về một số nguyên cho biết vị trí tương đối của chúng trong thứ tự sắp xếp. |
2 | public static int Compare(string strA, string strB, bool ignoreCase ) Compares two specified string objects and returns an integer that indicates their relative position in the sort order. However, it ignores case if the Boolean parameter is true. |
3 | public static string Concat(string str0, string str1) Concatenates two string objects. |
4 | public static string Concat(string str0, string str1, string str2) Concatenates three string objects. |
5 | public static string Concat(string str0, string str1, string str2, string str3) Concatenates four string objects. |
6 | public bool Contains(string value) Returns a value indicating whether the specified String object occurs within this string. |
7 | public static string Copy(string str) Creates a new String object with the same value as the specified string. |
8 | public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) Copies a specified number of characters from a specified position of the String object to a specified position in an array of Unicode characters. |
9 | public bool EndsWith(string value) Determines whether the end of the string object matches the specified string. |
10 | public bool Equals(string value) Determines whether the current String object and the specified String object have the same value. |
11 | public static bool Equals(string a, string b) Determines whether two specified String objects have the same value. |
12 | public static string Format(string format, Object arg0) Replaces one or more format items in a specified string with the string representation of a specified object. |
13 | public int IndexOf(char value) Returns the zero-based index of the first occurrence of the specified Unicode character in the current string. |
14 | public int IndexOf(string value) Returns the zero-based index of the first occurrence of the specified string in this instance. |
15 | public int IndexOf(char value, int startIndex) Returns the zero-based index of the first occurrence of the specified Unicode character in this string, starting search at the specified character position. |
16 | public int IndexOf(string value, int startIndex) Returns the zero-based index of the first occurrence of the specified string in this instance, starting search at the specified character position. |
17 | public int IndexOfAny(char[] anyOf) Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters. |
18 | public int IndexOfAny(char[] anyOf, int startIndex) Returns the zero-based index of the first occurrence in this instance of any character in a specified array of Unicode characters, starting search at the specified character position. |
19 | public string Insert(int startIndex, string value) Returns a new string in which a specified string is inserted at a specified index position in the current string object. |
20 | public static bool IsNullOrEmpty(string value) Indicates whether the specified string is null or an Empty string. |
21 | public static string Join(string separator, params string[] value) Concatenates all the elements of a string array, using the specified separator between each element. |
22 | public static string Join(string separator, string[] value, int startIndex, int count) Concatenates the specified elements of a string array, using the specified separator between each element. |
23 | public int LastIndexOf(char value) Returns the zero-based index position of the last occurrence of the specified Unicode character within the current string object. |
24 | public int LastIndexOf(string value) Returns the zero-based index position of the last occurrence of a specified string within the current string object. |
25 | public string Remove(int startIndex) Removes all the characters in the current instance, beginning at a specified position and continuing through the last position, and returns the string. |
26 | public string Remove(int startIndex, int count) Removes the specified number of characters in the current string beginning at a specified position and returns the string. |
27 | public string Replace(char oldChar, char newChar) Replaces all occurrences of a specified Unicode character in the current string object with the specified Unicode character and returns the new string. |
28 | public string Replace(string oldValue, string newValue) Replaces all occurrences of a specified string in the current string object with the specified string and returns the new string. |
29 | public string[] Split(params char[] separator) Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array. |
30 | public string[] Split(char[] separator, int count) Returns a string array that contains the substrings in the current string object, delimited by elements of a specified Unicode character array. The int parameter specifies the maximum number of substrings to return. |
31 | public bool StartsWith(string value) Determines whether the beginning of this string instance matches the specified string. |
32 | public char[] ToCharArray() Returns a Unicode character array with all the characters in the current string object. |
33 | public char[] ToCharArray(int startIndex, int length) Returns a Unicode character array with all the characters in the current string object, starting from the specified index and up to the specified length. |
34 | public string ToLower() Returns a copy of this string converted to lowercase. |
35 | public string ToUpper() Returns a copy of this string converted to uppercase. |
36 | public string Trim() Removes all leading and trailing white-space characters from the current String object. |
You can visit MSDN library for the complete list of methods and String class constructors.
Examples
The following example demonstrates some of the methods mentioned above −
Comparing Strings
using System;
namespace StringApplication {
class StringProg {
static void Main(string[] args) {
string str1 = "This is test";
string str2 = "This is text";
if (String.Compare(str1, str2) == 0) {
Console.WriteLine(str1 + " and " + str2 + " are equal.");
} else {
Console.WriteLine(str1 + " and " + str2 + " are not equal.");
}
Console.ReadKey() ;
}
}
}
When the above code is compiled and executed, it produces the following result −
This is test and This is text are not equal.
String Contains String
using System;
namespace StringApplication {
class StringProg {
static void Main(string[] args) {
string str = "This is test";
if (str.Contains("test")) {
Console.WriteLine("The sequence 'test' was found.");
}
Console.ReadKey() ;
}
}
}
When the above code is compiled and executed, it produces the following result −
The sequence 'test' was found.
Getting a Substring
using System;
namespace StringApplication {
class StringProg {
static void Main(string[] args) {
string str = "Last night I dreamt of San Pedro";
Console.WriteLine(str);
string substr = str.Substring(23);
Console.WriteLine(substr);
}
}
}
When the above code is compiled and executed, it produces the following result −
San Pedro
Joining Strings
using System;
namespace StringApplication {
class StringProg {
static void Main(string[] args) {
string[] starray = new string[]{"Down the way nights are dark",
"And the sun shines daily on the mountain top",
"I took a trip on a sailing ship",
"And when I reached Jamaica",
"I made a stop"};
string str = String.Join("\n", starray);
Console.WriteLine(str);
}
}
}
When the above code is compiled and executed, it produces the following result −
Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop
In C#, a structure is a value type data type. It helps you to make a single variable hold related data of various data types. The struct keyword is used for creating a structure.
Structures are used to represent a record. Suppose you want to keep track of your books in a library. You might want to track the following attributes about each book −
- Title
- Author
- Subject
- Book ID
Defining a Structure
To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member for your program.
For example, here is the way you can declare the Book structure −
struct Books {
public string title;
public string author;
public string subject;
public int book_id;
};
The following program shows the use of the structure −
using System;
struct Books {
public string title;
public string author;
public string subject;
public int book_id;
};
public class testStructure {
public static void Main(string[] args) {
Books Book1; /* Declare Book1 of type Book */
Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Book1.title = "C Programming";
Book1.author = "Nuha Ali";
Book1.subject = "C Programming Tutorial";
Book1.book_id = 6495407;
/* book 2 specification */
Book2.title = "Telecom Billing";
Book2.author = "Zara Ali";
Book2.subject = "Telecom Billing Tutorial";
Book2.book_id = 6495700;
/* print Book1 info */
Console.WriteLine( "Book 1 title : {0}", Book1.title);
Console.WriteLine("Book 1 author : {0}", Book1.author);
Console.WriteLine("Book 1 subject : {0}", Book1.subject);
Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);
/* print Book2 info */
Console.WriteLine("Book 2 title : {0}", Book2.title);
Console.WriteLine("Book 2 author : {0}", Book2.author);
Console.WriteLine("Book 2 subject : {0}", Book2.subject);
Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);
Console.ReadKey();
}
}
When the above code is compiled and executed, it produces the following result −
Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
Features of C# Structures
You have already used a simple structure named Books. Structures in C# are quite different from that in traditional C or C++. The C# structures have the following features −
Structures can have methods, fields, indexers, properties, operator methods, and events.
Structures can have defined constructors, but not destructors. However, you cannot define a default constructor for a structure. The default constructor is automatically defined and cannot be changed.
Unlike classes, structures cannot inherit other structures or classes.
Structures cannot be used as a base for other structures or classes.
A structure can implement one or more interfaces.
Structure members cannot be specified as abstract, virtual, or protected.
When you create a struct object using the New operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the New operator.
If the New operator is not used, the fields remain unassigned and the object cannot be used until all the fields are initialized.
Class versus Structure
Classes and Structures have the following basic differences −
- classes are reference types and structs are value types
- structures do not support inheritance
- structures cannot have default constructor
In the light of the above discussions, let us rewrite the previous example −
using System;
struct Books {
private string title;
private string author;
private string subject;
private int book_id;
public void getValues(string t, string a, string s, int id) {
title = t;
author = a;
subject = s;
book_id = id;
}
public void display() {
Console.WriteLine("Title : {0}", title);
Console.WriteLine("Author : {0}", author);
Console.WriteLine("Subject : {0}", subject);
Console.WriteLine("Book_id :{0}", book_id);
}
};
public class testStructure {
public static void Main(string[] args) {
Books Book1 = new Books(); /* Declare Book1 of type Book */
Books Book2 = new Books(); /* Declare Book2 of type Book */
/* book 1 specification */
Book1.getValues("C Programming",
"Nuha Ali", "C Programming Tutorial",6495407);
/* book 2 specification */
Book2.getValues("Telecom Billing",
"Zara Ali", "Telecom Billing Tutorial", 6495700);
/* print Book1 info */
Book1.display();
/* print Book2 info */
Book2.display();
Console.ReadKey();
}
}
When the above code is compiled and executed, it produces the following result −
Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700
An enumeration is a set of named integer constants. An enumerated type is declared using the enum keyword.
C# enumerations are value data type. In other words, enumeration contains its own values and cannot inherit or cannot pass inheritance.
Declaring enum Variable
The general syntax for declaring an enumeration is −
enum <enum_name> {
enumeration list
};
Where,
The enum_name specifies the enumeration type name.
The enumeration list is a comma-separated list of identifiers.
Each of the symbols in the enumeration list stands for an integer value, one greater than the symbol that precedes it. By default, the value of the first enumeration symbol is 0. For example −
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
Example
The following example demonstrates use of enum variable −
using System;
namespace EnumApplication {
class EnumProgram {
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
static void Main(string[] args) {
int WeekdayStart = (int)Days.Mon;
int WeekdayEnd = (int)Days.Fri;
Console.WriteLine("Monday: {0}", WeekdayStart);
Console.WriteLine("Friday: {0}", WeekdayEnd);
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result −
Monday: 1
Friday: 5
When you define a class, you define a blueprint for a data type. This does not actually define any data, but it does define what the class name means. That is, what an object of the class consists of and what operations can be performed on that object. Objects are instances of a class. The methods and variables that constitute a class are called members of the class.
Defining a Class
A class definition starts with the keyword class followed by the class name; and the class body enclosed by a pair of curly braces. Following is the general form of a class definition −
<access specifier> class class_name {
// member variables
<access specifier> <data type> variable1;
<access specifier> <data type> variable2;
...
<access specifier> <data type> variableN;
// member methods
<access specifier> <return type> method1(parameter_list) {
// method body
}
<access specifier> <return type> method2(parameter_list) {
// method body
}
...
<access specifier> <return type> methodN(parameter_list) {
// method body
}
}
Note −
Access specifiers specify the access rules for the members as well as the class itself. If not mentioned, then the default access specifier for a class type is internal. Default access for the members is private.
Data type specifies the type of variable, and return type specifies the data type of the data the method returns, if any.
To access the class members, you use the dot (.) operator.
The dot operator links the name of an object with the name of a member.
The following example illustrates the concepts discussed so far −
using System;
namespace BoxApplication {
class Box {
public double length; // Length of a box
public double breadth; // Breadth of a box
public double height; // Height of a box
}
class Boxtester {
static void Main(string[] args) {
Box Box1 = new Box(); // Declare Box1 of type Box
Box Box2 = new Box(); // Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 specification
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// volume of box 1
volume = Box1.height * Box1.length * Box1.breadth;
Console.WriteLine("Volume of Box1 : {0}", volume);
// volume of box 2
volume = Box2.height * Box2.length * Box2.breadth;
Console.WriteLine("Volume of Box2 : {0}", volume);
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result −
Volume of Box1 : 210
Volume of Box2 : 1560
Member Functions and Encapsulation
A member function of a class is a function that has its definition or its prototype within the class definition similar to any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.
Member variables are the attributes of an object (from design perspective) and they are kept private to implement encapsulation. These variables can only be accessed using the public member functions.
Let us put above concepts to set and get the value of different class members in a class −
using System;
namespace BoxApplication {
class Box {
private double length; // Length of a box
private double breadth; // Breadth of a box
private double height; // Height of a box
public void setLength( double len ) {
length = len;
}
public void setBreadth( double bre ) {
breadth = bre;
}
public void setHeight( double hei ) {
height = hei;
}
public double getVolume() {
return length * breadth * height;
}
}
class Boxtester {
static void Main(string[] args) {
Box Box1 = new Box(); // Declare Box1 of type Box
Box Box2 = new Box();
double volume;
// Declare Box2 of type Box
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
Console.WriteLine("Volume of Box1 : {0}" ,volume);
// volume of box 2
volume = Box2.getVolume();
Console.WriteLine("Volume of Box2 : {0}", volume);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Volume of Box1 : 210
Volume of Box2 : 1560
Trình tạo C #
Một lớp học constructor là một hàm thành viên đặc biệt của một lớp được thực thi bất cứ khi nào chúng ta tạo các đối tượng mới của lớp đó.
Một phương thức khởi tạo có cùng tên với tên của lớp và nó không có bất kỳ kiểu trả về nào. Ví dụ sau giải thích khái niệm về hàm tạo:
using System;
namespace LineApplication {
class Line {
private double length; // Length of a line
public Line() {
Console.WriteLine("Object is being created");
}
public void setLength( double len ) {
length = len;
}
public double getLength() {
return length;
}
static void Main(string[] args) {
Line line = new Line();
// set line length
line.setLength(6.0);
Console.WriteLine("Length of line : {0}", line.getLength());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Object is being created
Length of line : 6
A default constructorkhông có bất kỳ tham số nào nhưng nếu bạn cần, một phương thức khởi tạo có thể có tham số. Các hàm tạo như vậy được gọi làparameterized constructors. Kỹ thuật này giúp bạn gán giá trị ban đầu cho một đối tượng tại thời điểm tạo ra nó như thể hiện trong ví dụ sau:
using System;
namespace LineApplication {
class Line {
private double length; // Length of a line
public Line(double len) { //Parameterized constructor
Console.WriteLine("Object is being created, length = {0}", len);
length = len;
}
public void setLength( double len ) {
length = len;
}
public double getLength() {
return length;
}
static void Main(string[] args) {
Line line = new Line(10.0);
Console.WriteLine("Length of line : {0}", line.getLength());
// set line length
line.setLength(6.0);
Console.WriteLine("Length of line : {0}", line.getLength());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Object is being created, length = 10
Length of line : 10
Length of line : 6
Bộ hủy C #
A destructorlà một hàm thành viên đặc biệt của một lớp được thực thi bất cứ khi nào một đối tượng của lớp đó vượt ra khỏi phạm vi. Adestructor có tên chính xác giống với tên của lớp có dấu ngã ở trước (~) và nó không thể trả về giá trị cũng như không thể nhận bất kỳ tham số nào.
Bộ hủy có thể rất hữu ích để giải phóng tài nguyên bộ nhớ trước khi thoát khỏi chương trình. Bộ hủy không thể được kế thừa hoặc quá tải.
Ví dụ sau giải thích khái niệm hàm hủy -
using System;
namespace LineApplication {
class Line {
private double length; // Length of a line
public Line() { // constructor
Console.WriteLine("Object is being created");
}
~Line() { //destructor
Console.WriteLine("Object is being deleted");
}
public void setLength( double len ) {
length = len;
}
public double getLength() {
return length;
}
static void Main(string[] args) {
Line line = new Line();
// set line length
line.setLength(6.0);
Console.WriteLine("Length of line : {0}", line.getLength());
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Object is being created
Length of line : 6
Object is being deleted
Các thành viên tĩnh của lớp C #
Chúng ta có thể xác định các thành viên lớp là tĩnh bằng cách sử dụng statictừ khóa. Khi chúng ta khai báo một thành viên của một lớp là static, điều đó có nghĩa là cho dù có bao nhiêu đối tượng của lớp được tạo ra thì cũng chỉ có một bản sao của thành viên tĩnh.
Từ khóa staticngụ ý rằng chỉ có một thể hiện của thành viên tồn tại cho một lớp. Các biến static được sử dụng để định nghĩa hằng số vì giá trị của chúng có thể được truy xuất bằng cách gọi lớp mà không cần tạo một thể hiện của nó. Các biến static có thể được khởi tạo bên ngoài hàm thành viên hoặc định nghĩa lớp. Bạn cũng có thể khởi tạo các biến tĩnh bên trong định nghĩa lớp.
Ví dụ sau minh họa việc sử dụng static variables -
using System;
namespace StaticVarApplication {
class StaticVar {
public static int num;
public void count() {
num++;
}
public int getNum() {
return num;
}
}
class StaticTester {
static void Main(string[] args) {
StaticVar s1 = new StaticVar();
StaticVar s2 = new StaticVar();
s1.count();
s1.count();
s1.count();
s2.count();
s2.count();
s2.count();
Console.WriteLine("Variable num for s1: {0}", s1.getNum());
Console.WriteLine("Variable num for s2: {0}", s2.getNum());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Variable num for s1: 6
Variable num for s2: 6
Bạn cũng có thể khai báo một member function như static. Các hàm như vậy chỉ có thể truy cập các biến tĩnh. Các hàm tĩnh tồn tại ngay cả trước khi đối tượng được tạo. Ví dụ sau minh họa việc sử dụngstatic functions -
using System;
namespace StaticVarApplication {
class StaticVar {
public static int num;
public void count() {
num++;
}
public static int getNum() {
return num;
}
}
class StaticTester {
static void Main(string[] args) {
StaticVar s = new StaticVar();
s.count();
s.count();
s.count();
Console.WriteLine("Variable num: {0}", StaticVar.getNum());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Variable num: 3
Một trong những khái niệm quan trọng nhất trong lập trình hướng đối tượng là tính kế thừa. Tính kế thừa cho phép chúng ta định nghĩa một lớp theo nghĩa của một lớp khác, giúp tạo và duy trì một ứng dụng dễ dàng hơn. Điều này cũng tạo cơ hội để sử dụng lại chức năng mã và tăng tốc thời gian thực hiện.
Khi tạo một lớp, thay vì viết các thành viên dữ liệu hoàn toàn mới và các hàm thành viên, lập trình viên có thể chỉ định rằng lớp mới sẽ kế thừa các thành viên của một lớp hiện có. Lớp hiện có này được gọi làbase lớp và lớp mới được gọi là derived lớp học.
Ý tưởng kế thừa thực hiện IS-Amối quan hệ. Ví dụ, động vật có vúIS A động vật, con chó IS-A động vật có vú do đó chó IS-A động vật cũng vậy, v.v.
Các lớp cơ sở và có nguồn gốc
Một lớp có thể được dẫn xuất từ nhiều lớp hoặc giao diện, có nghĩa là nó có thể kế thừa dữ liệu và chức năng từ nhiều lớp hoặc giao diện cơ sở.
Cú pháp được sử dụng trong C # để tạo các lớp dẫn xuất như sau:
<acess-specifier> class <base_class> {
...
}
class <derived_class> : <base_class> {
...
}
Hãy xem xét một Hình dạng lớp cơ sở và Hình chữ nhật lớp dẫn xuất của nó -
using System;
namespace InheritanceApplication {
class Shape {
public void setWidth(int w) {
width = w;
}
public void setHeight(int h) {
height = h;
}
protected int width;
protected int height;
}
// Derived class
class Rectangle: Shape {
public int getArea() {
return (width * height);
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle Rect = new Rectangle();
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
Console.WriteLine("Total area: {0}", Rect.getArea());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Total area: 35
Khởi tạo lớp cơ sở
Lớp dẫn xuất kế thừa các biến thành viên của lớp cơ sở và các phương thức thành viên. Do đó, đối tượng siêu lớp nên được tạo trước khi lớp con được tạo. Bạn có thể đưa ra hướng dẫn cho việc khởi tạo lớp cha trong danh sách khởi tạo thành viên.
Chương trình sau đây chứng minh điều này -
using System;
namespace RectangleApplication {
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class Tabletop : Rectangle {
private double cost;
public Tabletop(double l, double w) : base(l, w) { }
public double GetCost() {
double cost;
cost = GetArea() * 70;
return cost;
}
public void Display() {
base.Display();
Console.WriteLine("Cost: {0}", GetCost());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Tabletop t = new Tabletop(4.5, 7.5);
t.Display();
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Length: 4.5
Width: 7.5
Area: 33.75
Cost: 2362.5
Kế thừa nhiều trong C #
C# does not support multiple inheritance. Tuy nhiên, bạn có thể sử dụng các giao diện để thực hiện đa kế thừa. Chương trình sau đây chứng minh điều này -
using System;
namespace InheritanceApplication {
class Shape {
public void setWidth(int w) {
width = w;
}
public void setHeight(int h) {
height = h;
}
protected int width;
protected int height;
}
// Base class PaintCost
public interface PaintCost {
int getCost(int area);
}
// Derived class
class Rectangle : Shape, PaintCost {
public int getArea() {
return (width * height);
}
public int getCost(int area) {
return area * 70;
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle Rect = new Rectangle();
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// Print the area of the object.
Console.WriteLine("Total area: {0}", Rect.getArea());
Console.WriteLine("Total paint cost: ${0}" , Rect.getCost(area));
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Total area: 35
Total paint cost: $2450
Từ polymorphismnghĩa là có nhiều hình thức. Trong mô hình lập trình hướng đối tượng, tính đa hình thường được biểu thị là 'một giao diện, nhiều chức năng'.
Tính đa hình có thể là tĩnh hoặc động. Trongstatic polymorphism, phản hồi cho một hàm được xác định tại thời điểm biên dịch. Trongdynamic polymorphism, nó được quyết định tại thời điểm chạy.
Tính đa hình tĩnh
Cơ chế liên kết một hàm với một đối tượng trong thời gian biên dịch được gọi là liên kết sớm. Nó còn được gọi là ràng buộc tĩnh. C # cung cấp hai kỹ thuật để triển khai tính đa hình tĩnh. Họ là -
- Quá tải chức năng
- Người vận hành quá tải
Chúng ta thảo luận về nạp chồng toán tử trong chương tiếp theo.
Quá tải chức năng
Bạn có thể có nhiều định nghĩa cho cùng một tên hàm trong cùng một phạm vi. Định nghĩa của hàm phải khác nhau theo kiểu và / hoặc số lượng đối số trong danh sách đối số. Bạn không thể nạp chồng các khai báo hàm chỉ khác nhau theo kiểu trả về.
Ví dụ sau cho thấy sử dụng hàm print() để in các kiểu dữ liệu khác nhau -
using System;
namespace PolymorphismApplication {
class Printdata {
void print(int i) {
Console.WriteLine("Printing int: {0}", i );
}
void print(double f) {
Console.WriteLine("Printing float: {0}" , f);
}
void print(string s) {
Console.WriteLine("Printing string: {0}", s);
}
static void Main(string[] args) {
Printdata p = new Printdata();
// Call print to print integer
p.print(5);
// Call print to print float
p.print(500.263);
// Call print to print string
p.print("Hello C++");
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Printing int: 5
Printing float: 500.263
Printing string: Hello C++
Đa hình động
C # cho phép bạn tạo các lớp trừu tượng được sử dụng để cung cấp triển khai một phần lớp của một giao diện. Việc triển khai được hoàn thành khi một lớp dẫn xuất kế thừa từ nó.Abstractcác lớp chứa các phương thức trừu tượng, được thực hiện bởi lớp dẫn xuất. Các lớp dẫn xuất có chức năng chuyên biệt hơn.
Dưới đây là các quy tắc về các lớp trừu tượng -
Bạn không thể tạo một thể hiện của một lớp trừu tượng
Bạn không thể khai báo một phương thức trừu tượng bên ngoài một lớp trừu tượng
Khi một lớp được khai báo sealed, nó không thể được kế thừa, không thể khai báo các lớp trừu tượng.
Chương trình sau thể hiện một lớp trừu tượng:
using System;
namespace PolymorphismApplication {
abstract class Shape {
public abstract int area();
}
class Rectangle: Shape {
private int length;
private int width;
public Rectangle( int a = 0, int b = 0) {
length = a;
width = b;
}
public override int area () {
Console.WriteLine("Rectangle class area :");
return (width * length);
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle r = new Rectangle(10, 7);
double a = r.area();
Console.WriteLine("Area: {0}",a);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Rectangle class area :
Area: 70
Khi bạn có một hàm được xác định trong một lớp mà bạn muốn được triển khai trong (các) lớp kế thừa, bạn sử dụng virtualchức năng. Các hàm ảo có thể được triển khai khác nhau trong các lớp kế thừa khác nhau và việc gọi các hàm này sẽ được quyết định trong thời gian chạy.
Tính đa hình động được thực hiện bởi abstract classes và virtual functions.
Chương trình sau đây chứng minh điều này -
using System;
namespace PolymorphismApplication {
class Shape {
protected int width, height;
public Shape( int a = 0, int b = 0) {
width = a;
height = b;
}
public virtual int area() {
Console.WriteLine("Parent class area :");
return 0;
}
}
class Rectangle: Shape {
public Rectangle( int a = 0, int b = 0): base(a, b) {
}
public override int area () {
Console.WriteLine("Rectangle class area :");
return (width * height);
}
}
class Triangle: Shape {
public Triangle(int a = 0, int b = 0): base(a, b) {
}
public override int area() {
Console.WriteLine("Triangle class area :");
return (width * height / 2);
}
}
class Caller {
public void CallArea(Shape sh) {
int a;
a = sh.area();
Console.WriteLine("Area: {0}", a);
}
}
class Tester {
static void Main(string[] args) {
Caller c = new Caller();
Rectangle r = new Rectangle(10, 7);
Triangle t = new Triangle(10, 5);
c.CallArea(r);
c.CallArea(t);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Rectangle class area:
Area: 70
Triangle class area:
Area: 25
Bạn có thể xác định lại hoặc quá tải hầu hết các toán tử tích hợp sẵn có trong C #. Do đó, một lập trình viên cũng có thể sử dụng các toán tử với các kiểu do người dùng xác định. Các toán tử bị quá tải là các hàm có tên đặc biệt là từ khóaoperatortheo sau là ký hiệu cho toán tử đang được xác định. tương tự như bất kỳ hàm nào khác, toán tử nạp chồng có kiểu trả về và danh sách tham số.
Ví dụ, hãy xem qua hàm sau:
public static Box operator+ (Box b, Box c) {
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
Hàm trên thực hiện toán tử cộng (+) cho Box lớp do người dùng định nghĩa. Nó thêm các thuộc tính của hai đối tượng Box và trả về đối tượng Box kết quả.
Thực hiện quá tải nhà điều hành
Chương trình sau đây cho thấy việc triển khai hoàn chỉnh:
using System;
namespace OperatorOvlApplication {
class Box {
private double length; // Length of a box
private double breadth; // Breadth of a box
private double height; // Height of a box
public double getVolume() {
return length * breadth * height;
}
public void setLength( double len ) {
length = len;
}
public void setBreadth( double bre ) {
breadth = bre;
}
public void setHeight( double hei ) {
height = hei;
}
// Overload + operator to add two Box objects.
public static Box operator+ (Box b, Box c) {
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
}
class Tester {
static void Main(string[] args) {
Box Box1 = new Box(); // Declare Box1 of type Box
Box Box2 = new Box(); // Declare Box2 of type Box
Box Box3 = new Box(); // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
Console.WriteLine("Volume of Box1 : {0}", volume);
// volume of box 2
volume = Box2.getVolume();
Console.WriteLine("Volume of Box2 : {0}", volume);
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
Console.WriteLine("Volume of Box3 : {0}", volume);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
Các nhà khai thác có thể quá tải và không quá tải
Bảng sau đây mô tả khả năng quá tải của các toán tử trong C # -
Sr.No. | Nhà khai thác & Mô tả |
---|---|
1 | +, -, !, ~, ++, -- Các toán tử một ngôi này nhận một toán hạng và có thể được nạp chồng. |
2 | +, -, *, /, % Các toán tử nhị phân này nhận một toán hạng và có thể được nạp chồng. |
3 | ==, !=, <, >, <=, >= Các toán tử so sánh có thể bị quá tải. |
4 | &&, || Các toán tử logic có điều kiện không thể được nạp chồng trực tiếp. |
5 | +=, -=, *=, /=, %= Các toán tử gán không thể được nạp chồng. |
6 | =, ., ?:, ->, new, is, sizeof, typeof Các toán tử này không thể được nạp chồng. |
Thí dụ
Theo các thảo luận ở trên, chúng ta hãy mở rộng ví dụ trước và nạp chồng thêm một số toán tử nữa -
using System;
namespace OperatorOvlApplication {
class Box {
private double length; // Length of a box
private double breadth; // Breadth of a box
private double height; // Height of a box
public double getVolume() {
return length * breadth * height;
}
public void setLength( double len ) {
length = len;
}
public void setBreadth( double bre ) {
breadth = bre;
}
public void setHeight( double hei ) {
height = hei;
}
// Overload + operator to add two Box objects.
public static Box operator+ (Box b, Box c) {
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
public static bool operator == (Box lhs, Box rhs) {
bool status = false;
if (lhs.length == rhs.length && lhs.height == rhs.height && lhs.breadth == rhs.breadth) {
status = true;
}
return status;
}
public static bool operator !=(Box lhs, Box rhs) {
bool status = false;
if (lhs.length != rhs.length || lhs.height != rhs.height || lhs.breadth != rhs.breadth) {
status = true;
}
return status;
}
public static bool operator <(Box lhs, Box rhs) {
bool status = false;
if (lhs.length < rhs.length && lhs.height < rhs.height && lhs.breadth < rhs.breadth) {
status = true;
}
return status;
}
public static bool operator >(Box lhs, Box rhs) {
bool status = false;
if (lhs.length > rhs.length && lhs.height > rhs.height && lhs.breadth > rhs.breadth) {
status = true;
}
return status;
}
public static bool operator <=(Box lhs, Box rhs) {
bool status = false;
if (lhs.length <= rhs.length && lhs.height <= rhs.height && lhs.breadth <= rhs.breadth) {
status = true;
}
return status;
}
public static bool operator >=(Box lhs, Box rhs) {
bool status = false;
if (lhs.length >= rhs.length && lhs.height >= rhs.height && lhs.breadth >= rhs.breadth) {
status = true;
}
return status;
}
public override string ToString() {
return String.Format("({0}, {1}, {2})", length, breadth, height);
}
}
class Tester {
static void Main(string[] args) {
Box Box1 = new Box(); // Declare Box1 of type Box
Box Box2 = new Box(); // Declare Box2 of type Box
Box Box3 = new Box(); // Declare Box3 of type Box
Box Box4 = new Box();
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
//displaying the Boxes using the overloaded ToString():
Console.WriteLine("Box 1: {0}", Box1.ToString());
Console.WriteLine("Box 2: {0}", Box2.ToString());
// volume of box 1
volume = Box1.getVolume();
Console.WriteLine("Volume of Box1 : {0}", volume);
// volume of box 2
volume = Box2.getVolume();
Console.WriteLine("Volume of Box2 : {0}", volume);
// Add two object as follows:
Box3 = Box1 + Box2;
Console.WriteLine("Box 3: {0}", Box3.ToString());
// volume of box 3
volume = Box3.getVolume();
Console.WriteLine("Volume of Box3 : {0}", volume);
//comparing the boxes
if (Box1 > Box2)
Console.WriteLine("Box1 is greater than Box2");
else
Console.WriteLine("Box1 is greater than Box2");
if (Box1 < Box2)
Console.WriteLine("Box1 is less than Box2");
else
Console.WriteLine("Box1 is not less than Box2");
if (Box1 >= Box2)
Console.WriteLine("Box1 is greater or equal to Box2");
else
Console.WriteLine("Box1 is not greater or equal to Box2");
if (Box1 <= Box2)
Console.WriteLine("Box1 is less or equal to Box2");
else
Console.WriteLine("Box1 is not less or equal to Box2");
if (Box1 != Box2)
Console.WriteLine("Box1 is not equal to Box2");
else
Console.WriteLine("Box1 is not greater or equal to Box2");
Box4 = Box3;
if (Box3 == Box4)
Console.WriteLine("Box3 is equal to Box4");
else
Console.WriteLine("Box3 is not equal to Box4");
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Box 1: (6, 7, 5)
Box 2: (12, 13, 10)
Volume of Box1 : 210
Volume of Box2 : 1560
Box 3: (18, 20, 15)
Volume of Box3 : 5400
Box1 is not greater than Box2
Box1 is less than Box2
Box1 is not greater or equal to Box2
Box1 is less or equal to Box2
Box1 is not equal to Box2
Box3 is equal to Box4
Một giao diện được định nghĩa là một hợp đồng cú pháp mà tất cả các lớp kế thừa giao diện phải tuân theo. Giao diện xác định'what' một phần của hợp đồng cú pháp và các lớp dẫn xuất xác định 'how' một phần của hợp đồng cú pháp.
Giao diện xác định các thuộc tính, phương thức và sự kiện, là các thành viên của giao diện. Giao diện chỉ chứa phần khai báo của các thành viên. Lớp dẫn xuất có trách nhiệm xác định các thành viên. Nó thường giúp cung cấp một cấu trúc chuẩn mà các lớp dẫn xuất sẽ tuân theo.
Các lớp trừu tượng ở một mức độ nào đó phục vụ cùng một mục đích, tuy nhiên, chúng chủ yếu được sử dụng khi chỉ có một số phương thức được khai báo bởi lớp cơ sở và lớp dẫn xuất thực hiện các chức năng.
Khai báo giao diện
Các giao diện được khai báo bằng từ khóa interface. Nó tương tự như khai báo lớp. Các câu lệnh giao diện được công khai theo mặc định. Sau đây là một ví dụ về khai báo giao diện:
public interface ITransactions {
// interface members
void showTransaction();
double getAmount();
}
Thí dụ
Ví dụ sau minh họa việc triển khai giao diện trên:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
namespace InterfaceApplication {
public interface ITransactions {
// interface members
void showTransaction();
double getAmount();
}
public class Transaction : ITransactions {
private string tCode;
private string date;
private double amount;
public Transaction() {
tCode = " ";
date = " ";
amount = 0.0;
}
public Transaction(string c, string d, double a) {
tCode = c;
date = d;
amount = a;
}
public double getAmount() {
return amount;
}
public void showTransaction() {
Console.WriteLine("Transaction: {0}", tCode);
Console.WriteLine("Date: {0}", date);
Console.WriteLine("Amount: {0}", getAmount());
}
}
class Tester {
static void Main(string[] args) {
Transaction t1 = new Transaction("001", "8/10/2012", 78900.00);
Transaction t2 = new Transaction("002", "9/10/2012", 451900.00);
t1.showTransaction();
t2.showTransaction();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Transaction: 001
Date: 8/10/2012
Amount: 78900
Transaction: 002
Date: 9/10/2012
Amount: 451900
A namespaceđược thiết kế để cung cấp một cách để giữ cho một bộ tên riêng biệt với một bộ tên khác. Tên lớp được khai báo trong một không gian tên không xung đột với các tên lớp tương tự được khai báo trong vùng tên khác.
Xác định không gian tên
Định nghĩa không gian tên bắt đầu bằng từ khóa namespace theo sau là tên không gian tên như sau:
namespace namespace_name {
// code declarations
}
Để gọi phiên bản hỗ trợ không gian tên của hàm hoặc biến, hãy thêm vào trước tên không gian tên như sau:
namespace_name.item_name;
Chương trình sau minh họa việc sử dụng không gian tên:
using System;
namespace first_space {
class namespace_cl {
public void func() {
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space {
class namespace_cl {
public void func() {
Console.WriteLine("Inside second_space");
}
}
}
class TestClass {
static void Main(string[] args) {
first_space.namespace_cl fc = new first_space.namespace_cl();
second_space.namespace_cl sc = new second_space.namespace_cl();
fc.func();
sc.func();
Console.ReadKey();
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Inside first_space
Inside second_space
Việc sử dụng Từ khoá
Các usingtừ khóa nói rằng chương trình đang sử dụng các tên trong không gian tên đã cho. Ví dụ: chúng tôi đang sử dụngSystemkhông gian tên trong các chương trình của chúng tôi. Bảng điều khiển lớp được định nghĩa ở đó. Chúng tôi chỉ viết -
Console.WriteLine ("Hello there");
Chúng tôi có thể đã viết tên đầy đủ đủ điều kiện là -
System.Console.WriteLine("Hello there");
Bạn cũng có thể tránh thêm các không gian tên với usingchỉ thị không gian tên. Chỉ thị này cho trình biên dịch biết rằng mã tiếp theo đang sử dụng tên trong không gian tên được chỉ định. Do đó, không gian tên được ngụ ý cho đoạn mã sau:
Hãy để chúng tôi viết lại ví dụ trước của chúng tôi, bằng cách sử dụng chỉ thị -
using System;
using first_space;
using second_space;
namespace first_space {
class abc {
public void func() {
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space {
class efg {
public void func() {
Console.WriteLine("Inside second_space");
}
}
}
class TestClass {
static void Main(string[] args) {
abc fc = new abc();
efg sc = new efg();
fc.func();
sc.func();
Console.ReadKey();
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Inside first_space
Inside second_space
Không gian tên lồng nhau
Bạn có thể xác định một không gian tên bên trong một không gian tên khác như sau:
namespace namespace_name1 {
// code declarations
namespace namespace_name2 {
// code declarations
}
}
Bạn có thể truy cập các thành viên của không gian tên lồng nhau bằng cách sử dụng toán tử dấu chấm (.) Như sau:
using System;
using first_space;
using first_space.second_space;
namespace first_space {
class abc {
public void func() {
Console.WriteLine("Inside first_space");
}
}
namespace second_space {
class efg {
public void func() {
Console.WriteLine("Inside second_space");
}
}
}
}
class TestClass {
static void Main(string[] args) {
abc fc = new abc();
efg sc = new efg();
fc.func();
sc.func();
Console.ReadKey();
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Inside first_space
Inside second_space
Các chỉ thị tiền xử lý cung cấp hướng dẫn cho trình biên dịch để xử lý trước thông tin trước khi quá trình biên dịch thực sự bắt đầu.
Tất cả các chỉ thị tiền xử lý bắt đầu bằng # và chỉ các ký tự khoảng trắng mới có thể xuất hiện trước một chỉ thị tiền xử lý trên một dòng. Các chỉ thị tiền xử lý không phải là các câu lệnh, vì vậy chúng không kết thúc bằng dấu chấm phẩy (;).
Trình biên dịch C # không có bộ tiền xử lý riêng; tuy nhiên, các chỉ thị được xử lý như thể có một. Trong C #, các chỉ thị tiền xử lý được sử dụng để giúp biên dịch có điều kiện. Không giống như các chỉ thị C và C ++, chúng không được sử dụng để tạo macro. Chỉ thị tiền xử lý phải là lệnh duy nhất trên một dòng.
Chỉ thị tiền xử lý trong C #
Bảng sau liệt kê các chỉ thị tiền xử lý có sẵn trong C # -
Sr.No. | Chỉ thị & Mô tả về Bộ tiền xử lý |
---|---|
1 | #define Nó xác định một chuỗi các ký tự, được gọi là ký hiệu. |
2 | #undef Nó cho phép bạn hủy xác định một biểu tượng. |
3 | #if Nó cho phép kiểm tra một biểu tượng hoặc các biểu tượng để xem liệu chúng có đánh giá đúng hay không. |
4 | #else Nó cho phép tạo một chỉ thị có điều kiện phức hợp, cùng với #if. |
5 | #elif Nó cho phép tạo một chỉ thị có điều kiện phức hợp. |
6 | #endif Chỉ định phần cuối của một chỉ thị có điều kiện. |
7 | #line Nó cho phép bạn sửa đổi số dòng của trình biên dịch và (tùy chọn) đầu ra tên tệp cho các lỗi và cảnh báo. |
số 8 | #error Nó cho phép tạo ra một lỗi từ một vị trí cụ thể trong mã của bạn. |
9 | #warning Nó cho phép tạo cảnh báo cấp một từ một vị trí cụ thể trong mã của bạn. |
10 | #region Nó cho phép bạn chỉ định một khối mã mà bạn có thể mở rộng hoặc thu gọn khi sử dụng tính năng phác thảo của Visual Studio Code Editor. |
11 | #endregion Nó đánh dấu sự kết thúc của khối # khu vực. |
#Define Preprocessor
Chỉ thị tiền xử lý #define tạo các hằng số tượng trưng.
#define cho phép bạn xác định một ký hiệu sao cho bằng cách sử dụng ký hiệu đó làm biểu thức được chuyển đến chỉ thị #if, biểu thức sẽ đánh giá là true. Cú pháp của nó như sau:
#define symbol
Chương trình sau đây minh họa điều này -
#define PI
using System;
namespace PreprocessorDAppl {
class Program {
static void Main(string[] args) {
#if (PI)
Console.WriteLine("PI is defined");
#else
Console.WriteLine("PI is not defined");
#endif
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
PI is defined
Chỉ thị có điều kiện
Bạn có thể sử dụng chỉ thị #if để tạo một chỉ thị có điều kiện. Các chỉ thị có điều kiện rất hữu ích để kiểm tra một ký hiệu hoặc các ký hiệu để kiểm tra xem chúng có đánh giá là đúng hay không. Nếu chúng đánh giá là true, trình biên dịch sẽ đánh giá tất cả mã giữa #if và chỉ thị tiếp theo.
Cú pháp cho chỉ thị có điều kiện là:
#if symbol [operator symbol]...
Trong đó, biểu tượng là tên của biểu tượng bạn muốn kiểm tra. Bạn cũng có thể sử dụng true và false hoặc thêm ký hiệu bằng toán tử phủ định.
Ký hiệu toán tử là toán tử được sử dụng để đánh giá ký hiệu. Các nhà khai thác có thể là một trong những người sau:
- == (bình đẳng)
- ! = (bất bình đẳng)
- && (và)
- || (hoặc là)
Bạn cũng có thể nhóm các ký hiệu và toán tử với dấu ngoặc đơn. Các chỉ thị có điều kiện được sử dụng để biên dịch mã cho một bản dựng gỡ lỗi hoặc khi biên dịch cho một cấu hình cụ thể. Chỉ thị có điều kiện bắt đầu bằng#if chỉ thị phải được chấm dứt một cách rõ ràng bằng một #endif chỉ thị.
Chương trình sau minh họa việc sử dụng các lệnh có điều kiện:
#define DEBUG
#define VC_V10
using System;
public class TestClass {
public static void Main() {
#if (DEBUG && !VC_V10)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && VC_V10)
Console.WriteLine("VC_V10 is defined");
#elif (DEBUG && VC_V10)
Console.WriteLine("DEBUG and VC_V10 are defined");
#else
Console.WriteLine("DEBUG and VC_V10 are not defined");
#endif
Console.ReadKey();
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
DEBUG and VC_V10 are defined
A regular expressionlà một mẫu có thể được đối sánh với văn bản đầu vào. Khuôn khổ .Net cung cấp một công cụ biểu thức chính quy cho phép đối sánh như vậy. Một mẫu bao gồm một hoặc nhiều ký tự, toán tử hoặc cấu trúc.
Cấu trúc để xác định cụm từ thông dụng
Có nhiều loại ký tự, toán tử và cấu trúc khác nhau cho phép bạn xác định các biểu thức chính quy. Nhấp vào các liên kết sau để tìm các cấu trúc này.
Nhân vật trốn thoát
Các lớp nhân vật
Anchors
Nhóm các cấu trúc
Quantifiers
Cấu trúc phản hồi
Cấu trúc thay thế
Substitutions
Các cấu trúc khác
Lớp Regex
Lớp Regex được sử dụng để biểu diễn một biểu thức chính quy. Nó có các phương pháp thường được sử dụng sau:
Sr.No. | Phương pháp & Mô tả |
---|---|
1 | public bool IsMatch(string input) Cho biết liệu biểu thức chính quy được chỉ định trong hàm tạo Regex có tìm thấy kết quả phù hợp trong chuỗi đầu vào được chỉ định hay không. |
2 | public bool IsMatch(string input, int startat) Cho biết liệu biểu thức chính quy được chỉ định trong hàm tạo Regex có tìm thấy khớp trong chuỗi đầu vào được chỉ định hay không, bắt đầu từ vị trí bắt đầu được chỉ định trong chuỗi. |
3 | public static bool IsMatch(string input, string pattern) Cho biết liệu biểu thức chính quy được chỉ định có tìm thấy khớp trong chuỗi đầu vào được chỉ định hay không. |
4 | public MatchCollection Matches(string input) Tìm kiếm chuỗi đầu vào được chỉ định cho tất cả các lần xuất hiện của một biểu thức chính quy. |
5 | public string Replace(string input, string replacement) Trong một chuỗi đầu vào được chỉ định, hãy thay thế tất cả các chuỗi khớp với mẫu biểu thức chính quy bằng một chuỗi thay thế đã chỉ định. |
6 | public string[] Split(string input) Tách một chuỗi đầu vào thành một mảng các chuỗi con tại các vị trí được xác định bởi một mẫu biểu thức chính quy được chỉ định trong hàm tạo Regex. |
Để có danh sách đầy đủ các phương thức và thuộc tính, vui lòng đọc tài liệu của Microsoft về C #.
ví dụ 1
Ví dụ sau phù hợp với các từ bắt đầu bằng 'S' -
using System;
using System.Text.RegularExpressions;
namespace RegExApplication {
class Program {
private static void showMatch(string text, string expr) {
Console.WriteLine("The Expression: " + expr);
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc) {
Console.WriteLine(m);
}
}
static void Main(string[] args) {
string str = "A Thousand Splendid Suns";
Console.WriteLine("Matching words that start with 'S': ");
showMatch(str, @"\bS\S*");
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Matching words that start with 'S':
The Expression: \bS\S*
Splendid
Suns
Ví dụ 2
Ví dụ sau phù hợp với các từ bắt đầu bằng 'm' và kết thúc bằng 'e' -
using System;
using System.Text.RegularExpressions;
namespace RegExApplication {
class Program {
private static void showMatch(string text, string expr) {
Console.WriteLine("The Expression: " + expr);
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc) {
Console.WriteLine(m);
}
}
static void Main(string[] args) {
string str = "make maze and manage to measure it";
Console.WriteLine("Matching words start with 'm' and ends with 'e':");
showMatch(str, @"\bm\S*e\b");
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Matching words start with 'm' and ends with 'e':
The Expression: \bm\S*e\b
make
maze
manage
measure
Ví dụ 3
Ví dụ này thay thế khoảng trắng thừa -
using System;
using System.Text.RegularExpressions;
namespace RegExApplication {
class Program {
static void Main(string[] args) {
string input = "Hello World ";
string pattern = "\\s+";
string replacement = " ";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
Console.WriteLine("Original String: {0}", input);
Console.WriteLine("Replacement String: {0}", result);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Original String: Hello World
Replacement String: Hello World
Một ngoại lệ là một vấn đề phát sinh trong quá trình thực hiện một chương trình. Ngoại lệ AC # là phản hồi cho một trường hợp ngoại lệ phát sinh trong khi chương trình đang chạy, chẳng hạn như nỗ lực chia cho không.
Ngoại lệ cung cấp một cách để chuyển quyền kiểm soát từ một phần của chương trình sang phần khác. Xử lý ngoại lệ C # được xây dựng dựa trên bốn từ khóa:try, catch, finallyvà throw.
try- Khối thử xác định một khối mã mà các ngoại lệ cụ thể được kích hoạt. Theo sau nó là một hoặc nhiều khối bắt.
catch- Một chương trình bắt một ngoại lệ với một trình xử lý ngoại lệ tại vị trí trong chương trình mà bạn muốn xử lý vấn đề. Từ khóa catch cho biết việc bắt một ngoại lệ.
finally- Khối cuối cùng được sử dụng để thực thi một tập hợp các câu lệnh đã cho, cho dù một ngoại lệ được ném hay không được ném. Ví dụ: nếu bạn mở một tệp, nó phải được đóng lại cho dù có một ngoại lệ nào được đưa ra hay không.
throw- Một chương trình ném ra một ngoại lệ khi một vấn đề xuất hiện. Điều này được thực hiện bằng cách sử dụng một từ khóa ném.
Cú pháp
Giả sử một khối tạo ra một ngoại lệ, một phương pháp sẽ bắt một ngoại lệ bằng cách sử dụng kết hợp các từ khóa try and catch. Một khối try / catch được đặt xung quanh mã có thể tạo ra một ngoại lệ. Mã trong khối try / catch được gọi là mã được bảo vệ và cú pháp để sử dụng try / catch trông giống như sau:
try {
// statements causing exception
} catch( ExceptionName e1 ) {
// error handling code
} catch( ExceptionName e2 ) {
// error handling code
} catch( ExceptionName eN ) {
// error handling code
} finally {
// statements to be executed
}
Bạn có thể liệt kê nhiều câu lệnh bắt để bắt các loại ngoại lệ khác nhau trong trường hợp khối try của bạn tạo ra nhiều hơn một ngoại lệ trong các tình huống khác nhau.
Các lớp ngoại lệ trong C #
Các ngoại lệ của C # được đại diện bởi các lớp. Các lớp ngoại lệ trong C # chủ yếu được dẫn xuất trực tiếp hoặc gián tiếp từSystem.Exceptionlớp học. Một số lớp ngoại lệ bắt nguồn từ lớp System.Exception làSystem.ApplicationException và System.SystemException các lớp học.
Các System.ApplicationExceptionlớp hỗ trợ các ngoại lệ do các chương trình ứng dụng tạo ra. Do đó, các ngoại lệ được định nghĩa bởi các lập trình viên nên bắt nguồn từ lớp này.
Các System.SystemException lớp là lớp cơ sở cho tất cả ngoại lệ hệ thống được xác định trước.
Bảng sau cung cấp một số lớp ngoại lệ được xác định trước có nguồn gốc từ lớp Sytem.SystemException -
Sr.No. | Lớp ngoại lệ & Mô tả |
---|---|
1 | System.IO.IOException Xử lý lỗi I / O. |
2 | System.IndexOutOfRangeException Xử lý các lỗi được tạo ra khi một phương thức tham chiếu đến chỉ mục mảng nằm ngoài phạm vi. |
3 | System.ArrayTypeMismatchException Xử lý các lỗi được tạo ra khi kiểu không khớp với kiểu mảng. |
4 | System.NullReferenceException Xử lý các lỗi được tạo ra từ việc tham chiếu một đối tượng rỗng. |
5 | System.DivideByZeroException Xử lý các lỗi phát sinh từ việc chia cổ tức bằng 0. |
6 | System.InvalidCastException Xử lý các lỗi phát sinh trong quá trình đánh máy. |
7 | System.OutOfMemoryException Xử lý các lỗi do không đủ bộ nhớ trống. |
số 8 | System.StackOverflowException Xử lý các lỗi tạo ra từ tràn ngăn xếp. |
Xử lý ngoại lệ
C # cung cấp một giải pháp có cấu trúc để xử lý ngoại lệ dưới dạng khối thử và bắt. Sử dụng các khối này, các câu lệnh chương trình cốt lõi được tách biệt với các câu lệnh xử lý lỗi.
Các khối xử lý lỗi này được thực hiện bằng cách sử dụng try, catchvà finallytừ khóa. Sau đây là một ví dụ về việc ném một ngoại lệ khi điều kiện chia cho 0 xảy ra:
using System;
namespace ErrorHandlingApplication {
class DivNumbers {
int result;
DivNumbers() {
result = 0;
}
public void division(int num1, int num2) {
try {
result = num1 / num2;
} catch (DivideByZeroException e) {
Console.WriteLine("Exception caught: {0}", e);
} finally {
Console.WriteLine("Result: {0}", result);
}
}
static void Main(string[] args) {
DivNumbers d = new DivNumbers();
d.division(25, 0);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Exception caught: System.DivideByZeroException: Attempted to divide by zero.
at ...
Result: 0
Tạo ngoại lệ do người dùng xác định
Bạn cũng có thể xác định ngoại lệ của riêng mình. Các lớp ngoại lệ do người dùng xác định có nguồn gốc từExceptionlớp học. Ví dụ sau đây chứng minh điều này -
using System;
namespace UserDefinedException {
class TestTemperature {
static void Main(string[] args) {
Temperature temp = new Temperature();
try {
temp.showTemp();
} catch(TempIsZeroException e) {
Console.WriteLine("TempIsZeroException: {0}", e.Message);
}
Console.ReadKey();
}
}
}
public class TempIsZeroException: Exception {
public TempIsZeroException(string message): base(message) {
}
}
public class Temperature {
int temperature = 0;
public void showTemp() {
if(temperature == 0) {
throw (new TempIsZeroException("Zero Temperature found"));
} else {
Console.WriteLine("Temperature: {0}", temperature);
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
TempIsZeroException: Zero Temperature found
Ném đồ vật
Bạn có thể ném một đối tượng nếu nó có nguồn gốc trực tiếp hoặc gián tiếp từ System.Exceptionlớp học. Bạn có thể sử dụng câu lệnh ném trong khối catch để ném đối tượng hiện tại dưới dạng:
Catch(Exception e) {
...
Throw e
}
A filelà tập hợp dữ liệu được lưu trữ trong đĩa với tên cụ thể và đường dẫn thư mục. Khi một tệp được mở để đọc hoặc ghi, nó sẽ trở thànhstream.
Luồng về cơ bản là chuỗi các byte đi qua đường truyền thông. Có hai luồng chính:input stream và output stream. Các input stream được sử dụng để đọc dữ liệu từ tệp (thao tác đọc) và output stream được sử dụng để ghi vào tệp (thao tác ghi).
Các lớp C # I / O
Không gian tên System.IO có nhiều lớp khác nhau được sử dụng để thực hiện nhiều thao tác với tệp, chẳng hạn như tạo và xóa tệp, đọc hoặc ghi vào tệp, đóng tệp, v.v.
Bảng sau đây cho thấy một số lớp không trừu tượng thường được sử dụng trong không gian tên System.IO:
Sr.No. | I / O Class & Description |
---|---|
1 | BinaryReader Đọc dữ liệu nguyên thủy từ một luồng nhị phân. |
2 | BinaryWriter Viết dữ liệu nguyên thủy ở định dạng nhị phân. |
3 | BufferedStream Nơi lưu trữ tạm thời cho một luồng byte. |
4 | Directory Giúp thao tác cấu trúc thư mục. |
5 | DirectoryInfo Được sử dụng để thực hiện các hoạt động trên thư mục. |
6 | DriveInfo Cung cấp thông tin cho các ổ đĩa. |
7 | File Giúp thao tác với các tập tin. |
số 8 | FileInfo Được sử dụng để thực hiện các thao tác trên tệp. |
9 | FileStream Được sử dụng để đọc và ghi vào bất kỳ vị trí nào trong tệp. |
10 | MemoryStream Được sử dụng để truy cập ngẫu nhiên vào dữ liệu truyền trực tuyến được lưu trữ trong bộ nhớ. |
11 | Path Thực hiện các thao tác trên thông tin đường dẫn. |
12 | StreamReader Được sử dụng để đọc các ký tự từ một luồng byte. |
13 | StreamWriter Được sử dụng để ghi các ký tự vào một luồng. |
14 | StringReader Được sử dụng để đọc từ bộ đệm chuỗi. |
15 | StringWriter Được sử dụng để ghi vào một bộ đệm chuỗi. |
Lớp FileStream
Các FileStreamlớp trong không gian tên System.IO giúp đọc, ghi và đóng tệp. Lớp này bắt nguồn từ lớp trừu tượng Stream.
Bạn cần tạo một FileStreamđể tạo một tệp mới hoặc mở một tệp hiện có. Cú pháp để tạoFileStream đối tượng như sau:
FileStream <object_name> = new FileStream( <file_name>, <FileMode Enumerator>,
<FileAccess Enumerator>, <FileShare Enumerator>);
Ví dụ: chúng tôi tạo một đối tượng FileStream F để đọc một tệp có tên sample.txt as shown -
FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read,
FileShare.Read);
Sr.No. | Mô tả về Thông Số |
---|---|
1 | FileMode Các FileModeđiều tra viên xác định các phương pháp khác nhau để mở tệp. Các thành viên của bảng kê FileMode là:
|
2 | FileAccess FileAccess điều tra viên có các thành viên: Read, ReadWrite và Write. |
3 | FileShare FileShare Điều tra viên có các thành viên sau:
|
Thí dụ
Chương trình sau minh họa việc sử dụng FileStream lớp học -
using System;
using System.IO;
namespace FileIOApplication {
class Program {
static void Main(string[] args) {
FileStream F = new FileStream("test.dat", FileMode.OpenOrCreate,
FileAccess.ReadWrite);
for (int i = 1; i <= 20; i++) {
F.WriteByte((byte)i);
}
F.Position = 0;
for (int i = 0; i <= 20; i++) {
Console.Write(F.ReadByte() + " ");
}
F.Close();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1
Thao tác tệp nâng cao trong C #
Ví dụ trước cung cấp các thao tác đơn giản với tệp trong C #. Tuy nhiên, để sử dụng sức mạnh to lớn của các lớp C # System.IO, bạn cần biết các thuộc tính và phương thức thường được sử dụng của các lớp này.
Sr.No. | Chủ đề Mô tả |
---|---|
1 | Đọc và ghi vào tệp văn bản Nó liên quan đến việc đọc và ghi vào các tệp văn bản. CácStreamReader và StreamWriter lớp giúp hoàn thành nó. |
2 | Đọc và ghi vào tệp nhị phân Nó liên quan đến việc đọc và ghi vào các tệp nhị phân. CácBinaryReader và BinaryWriter lớp giúp thực hiện điều này. |
3 | Thao tác với hệ thống tệp Windows Nó cung cấp cho người lập trình C # khả năng duyệt và định vị các tệp và thư mục Windows. |
An attributelà một thẻ khai báo được sử dụng để truyền tải thông tin đến thời gian chạy về hành vi của các phần tử khác nhau như lớp, phương thức, cấu trúc, bộ liệt kê, hợp ngữ, v.v. trong chương trình của bạn. Bạn có thể thêm thông tin khai báo vào chương trình bằng cách sử dụng một thuộc tính. Thẻ khai báo được mô tả bằng dấu ngoặc vuông ([]) đặt phía trên phần tử mà nó được sử dụng.
Các thuộc tính được sử dụng để thêm siêu dữ liệu, chẳng hạn như hướng dẫn trình biên dịch và các thông tin khác như nhận xét, mô tả, phương thức và lớp vào chương trình. .Net Framework cung cấp hai loại thuộc tính: thuộc tính được xác định trước và thuộc tính được xây dựng tùy chỉnh .
Chỉ định một thuộc tính
Cú pháp để chỉ định một thuộc tính như sau:
[attribute(positional_parameters, name_parameter = value, ...)]
element
Tên của thuộc tính và các giá trị của nó được chỉ định trong dấu ngoặc vuông, trước phần tử mà thuộc tính được áp dụng. Tham số vị trí chỉ định thông tin cần thiết và tham số tên chỉ định thông tin tùy chọn.
Thuộc tính được xác định trước
.Net Framework cung cấp ba thuộc tính được xác định trước:
- AttributeUsage
- Conditional
- Obsolete
AttributeUsage
Thuộc tính được xác định trước AttributeUsagemô tả cách một lớp thuộc tính tùy chỉnh có thể được sử dụng. Nó chỉ định các loại mặt hàng mà thuộc tính có thể được áp dụng.
Cú pháp để chỉ định thuộc tính này như sau:
[AttributeUsage (
validon,
AllowMultiple = allowmultiple,
Inherited = inherited
)]
Ở đâu,
Tham số validon chỉ định các phần tử ngôn ngữ mà thuộc tính có thể được đặt vào. Nó là sự kết hợp của giá trị của một AttributeTargets của người điều tra . Giá trị mặc định là AttributeTargets.All .
Tham số allowmultiple (tùy chọn) cung cấp giá trị cho thuộc tính AllowMultiple của thuộc tính này, một giá trị Boolean. Nếu điều này là đúng, thuộc tính này là đa dụng. Giá trị mặc định là false (sử dụng một lần).
Tham số được kế thừa (tùy chọn) cung cấp giá trị cho thuộc tính Được thừa kế của thuộc tính này, một giá trị Boolean. Nếu nó là true, thuộc tính được kế thừa bởi các lớp dẫn xuất. Giá trị mặc định là false (không được kế thừa).
Ví dụ,
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
Có điều kiện
Thuộc tính được xác định trước này đánh dấu một phương thức có điều kiện mà việc thực thi phụ thuộc vào một số nhận dạng tiền xử lý được chỉ định.
Nó gây ra việc biên dịch có điều kiện các cuộc gọi phương thức, tùy thuộc vào giá trị được chỉ định, chẳng hạn như Debug hoặc là Trace. Ví dụ, nó hiển thị giá trị của các biến trong khi gỡ lỗi mã.
Cú pháp để chỉ định thuộc tính này như sau:
[Conditional(
conditionalSymbol
)]
Ví dụ,
[Conditional("DEBUG")]
Ví dụ sau minh họa thuộc tính -
#define DEBUG
using System;
using System.Diagnostics;
public class Myclass {
[Conditional("DEBUG")]
public static void Message(string msg) {
Console.WriteLine(msg);
}
}
class Test {
static void function1() {
Myclass.Message("In Function 1.");
function2();
}
static void function2() {
Myclass.Message("In Function 2.");
}
public static void Main() {
Myclass.Message("In Main function.");
function1();
Console.ReadKey();
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main function
In Function 1
In Function 2
Lỗi thời
Thuộc tính được xác định trước này đánh dấu một thực thể chương trình không nên được sử dụng. Nó cho phép bạn thông báo cho trình biên dịch để loại bỏ một phần tử đích cụ thể. Ví dụ: khi một phương thức mới đang được sử dụng trong một lớp và nếu bạn vẫn muốn giữ lại phương thức cũ trong lớp, bạn có thể đánh dấu phương thức đó là lỗi thời bằng cách hiển thị thông báo phương thức mới nên được sử dụng thay vì phương thức cũ.
Cú pháp để chỉ định thuộc tính này như sau:
[Obsolete (
message
)]
[Obsolete (
message,
iserror
)]
Ở đâu,
Thông báo tham số , là một chuỗi mô tả lý do tại sao mặt hàng bị lỗi thời và cái gì để thay thế.
Tham số iserror , là một giá trị Boolean. Nếu giá trị của nó là true, trình biên dịch sẽ coi việc sử dụng mục là một lỗi. Giá trị mặc định là false (trình biên dịch tạo ra cảnh báo).
Chương trình sau đây chứng minh điều này -
using System;
public class MyClass {
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod() {
Console.WriteLine("It is the old method");
}
static void NewMethod() {
Console.WriteLine("It is the new method");
}
public static void Main() {
OldMethod();
}
}
Khi bạn cố gắng biên dịch chương trình, trình biên dịch sẽ đưa ra thông báo lỗi cho biết:
Don't use OldMethod, use NewMethod instead
Tạo thuộc tính tùy chỉnh
.Net Framework cho phép tạo các thuộc tính tùy chỉnh có thể được sử dụng để lưu trữ thông tin khai báo và có thể được truy xuất tại thời điểm chạy. Thông tin này có thể liên quan đến bất kỳ phần tử mục tiêu nào tùy thuộc vào tiêu chí thiết kế và nhu cầu ứng dụng.
Tạo và sử dụng các thuộc tính tùy chỉnh bao gồm bốn bước:
- Khai báo thuộc tính tùy chỉnh
- Tạo thuộc tính tùy chỉnh
- Áp dụng thuộc tính tùy chỉnh trên phần tử chương trình mục tiêu
- Truy cập các thuộc tính thông qua phản ánh
Bước cuối cùng liên quan đến việc viết một chương trình đơn giản để đọc qua siêu dữ liệu để tìm các ký hiệu khác nhau. Siêu dữ liệu là dữ liệu về dữ liệu hoặc thông tin được sử dụng để mô tả dữ liệu khác. Chương trình này nên sử dụng phản xạ để truy cập các thuộc tính trong thời gian chạy. Điều này chúng ta sẽ thảo luận trong chương tiếp theo.
Khai báo thuộc tính tùy chỉnh
Một thuộc tính tùy chỉnh mới phải được bắt nguồn từ System.Attributelớp học. Ví dụ,
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
Trong đoạn mã trước, chúng ta đã khai báo một thuộc tính tùy chỉnh có tên là DeBugInfo .
Tạo thuộc tính tùy chỉnh
Hãy để chúng tôi xây dựng một thuộc tính tùy chỉnh có tên DeBugInfo , thuộc tính này lưu trữ thông tin thu được bằng cách gỡ lỗi bất kỳ chương trình nào. Hãy để nó lưu trữ các thông tin sau -
- Số mã của lỗi
- Tên của nhà phát triển đã xác định lỗi
- Ngày xem xét mã cuối cùng
- Thông báo chuỗi để lưu trữ nhận xét của nhà phát triển
Lớp DeBugInfo có ba thuộc tính riêng để lưu trữ ba thông tin đầu tiên và thuộc tính chung để lưu thông báo. Do đó, số lỗi, tên nhà phát triển và ngày xem xét là các tham số vị trí của lớp DeBugInfo và thông báo là một tham số tùy chọn hoặc có tên.
Mỗi thuộc tính phải có ít nhất một hàm tạo. Các tham số vị trí phải được chuyển qua hàm tạo. Đoạn mã sau hiển thị lớp DeBugInfo :
//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute {
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d) {
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo {
get {
return bugNo;
}
}
public string Developer {
get {
return developer;
}
}
public string LastReview {
get {
return lastReview;
}
}
public string Message {
get {
return message;
}
set {
message = value;
}
}
}
Áp dụng thuộc tính tùy chỉnh
Thuộc tính được áp dụng bằng cách đặt nó ngay trước mục tiêu của nó -
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
public double GetArea() {
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
Trong chương tiếp theo, chúng ta lấy thông tin thuộc tính bằng cách sử dụng đối tượng lớp Reflection.
Reflectioncác đối tượng được sử dụng để lấy thông tin kiểu trong thời gian chạy. Các lớp cấp quyền truy cập vào siêu dữ liệu của một chương trình đang chạy nằm trongSystem.Reflection không gian tên.
Các System.Reflection không gian tên chứa các lớp cho phép bạn lấy thông tin về ứng dụng và thêm động các kiểu, giá trị và đối tượng vào ứng dụng.
Các ứng dụng của sự phản chiếu
Reflection có các ứng dụng sau:
Nó cho phép xem thông tin thuộc tính trong thời gian chạy.
Nó cho phép kiểm tra các kiểu khác nhau trong một lắp ráp và khởi tạo các kiểu này.
Nó cho phép liên kết muộn với các phương thức và thuộc tính
Nó cho phép tạo các kiểu mới trong thời gian chạy và sau đó thực hiện một số tác vụ bằng cách sử dụng các kiểu đó.
Xem siêu dữ liệu
Chúng tôi đã đề cập trong chương trước rằng sử dụng phản chiếu, bạn có thể xem thông tin thuộc tính.
Các MemberInfo đối tượng của System.Reflectionlớp cần được khởi tạo để khám phá các thuộc tính được liên kết với một lớp. Để làm điều này, bạn xác định một đối tượng của lớp đích, như sau:
System.Reflection.MemberInfo info = typeof(MyClass);
Chương trình sau đây chứng minh điều này -
using System;
[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
public readonly string Url;
public string Topic // Topic is a named parameter {
get {
return topic;
}
set {
topic = value;
}
}
public HelpAttribute(string url) // url is a positional parameter {
this.Url = url;
}
private string topic;
}
[HelpAttribute("Information on the class MyClass")]
class MyClass {
}
namespace AttributeAppl {
class Program {
static void Main(string[] args) {
System.Reflection.MemberInfo info = typeof(MyClass);
object[] attributes = info.GetCustomAttributes(true);
for (int i = 0; i < attributes.Length; i++) {
System.Console.WriteLine(attributes[i]);
}
Console.ReadKey();
}
}
}
Khi nó được biên dịch và chạy, nó sẽ hiển thị tên của các thuộc tính tùy chỉnh được đính kèm với lớp MyClass -
HelpAttribute
Thí dụ
Trong ví dụ này, chúng tôi sử dụng thuộc tính DeBugInfo đã tạo trong chương trước và sử dụng phản xạ để đọc siêu dữ liệu trong lớp Rectangle .
using System;
using System.Reflection;
namespace BugFixApplication {
//a custom attribute BugFix to be
//assigned to a class and its members
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute {
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d) {
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo {
get {
return bugNo;
}
}
public string Developer {
get {
return developer;
}
}
public string LastReview {
get {
return lastReview;
}
}
public string Message {
get {
return message;
}
set {
message = value;
}
}
}
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
public double GetArea() {
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle(4.5, 7.5);
r.Display();
Type type = typeof(Rectangle);
//iterating through the attribtues of the Rectangle class
foreach (Object attributes in type.GetCustomAttributes(false)) {
DeBugInfo dbi = (DeBugInfo)attributes;
if (null != dbi) {
Console.WriteLine("Bug no: {0}", dbi.BugNo);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
//iterating through the method attribtues
foreach (MethodInfo m in type.GetMethods()) {
foreach (Attribute a in m.GetCustomAttributes(true)) {
DeBugInfo dbi = (DeBugInfo)a;
if (null != dbi) {
Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
}
Console.ReadLine();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks:
Propertieslà các thành viên được đặt tên của các lớp, cấu trúc và giao diện. Các biến hoặc phương thức thành viên trong một lớp hoặc các cấu trúc được gọiFields. Thuộc tính là phần mở rộng của các trường và được truy cập bằng cùng một cú pháp. Họ sử dụngaccessors qua đó các giá trị của các trường riêng có thể được đọc, ghi hoặc thao tác.
Thuộc tính không đặt tên cho các vị trí lưu trữ. Thay vào đó, họ cóaccessors đọc, ghi hoặc tính toán các giá trị của chúng.
Ví dụ, chúng ta có một lớp tên là Sinh viên, với các trường riêng cho tuổi, tên và mã. Chúng ta không thể truy cập trực tiếp các trường này từ bên ngoài phạm vi lớp, nhưng chúng ta có thể có các thuộc tính để truy cập các trường riêng tư này.
Người truy cập
Các accessorcủa thuộc tính chứa các câu lệnh thực thi giúp nhận (đọc hoặc tính toán) hoặc thiết lập (ghi) thuộc tính. Khai báo trình truy cập có thể chứa trình truy cập nhận, trình truy cập đặt hoặc cả hai. Ví dụ -
// Declare a Code property of type string:
public string Code {
get {
return code;
}
set {
code = value;
}
}
// Declare a Name property of type string:
public string Name {
get {
return name;
}
set {
name = value;
}
}
// Declare a Age property of type int:
public int Age {
get {
return age;
}
set {
age = value;
}
}
Thí dụ
Ví dụ sau minh họa việc sử dụng các thuộc tính:
using System;
namespace tutorialspoint {
class Student {
private string code = "N.A";
private string name = "not known";
private int age = 0;
// Declare a Code property of type string:
public string Code {
get {
return code;
}
set {
code = value;
}
}
// Declare a Name property of type string:
public string Name {
get {
return name;
}
set {
name = value;
}
}
// Declare a Age property of type int:
public int Age {
get {
return age;
}
set {
age = value;
}
}
public override string ToString() {
return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
}
}
class ExampleDemo {
public static void Main() {
// Create a new Student object:
Student s = new Student();
// Setting code, name and the age of the student
s.Code = "001";
s.Name = "Zara";
s.Age = 9;
Console.WriteLine("Student Info: {0}", s);
//let us increase age
s.Age += 1;
Console.WriteLine("Student Info: {0}", s);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10
Thuộc tính trừu tượng
Một lớp trừu tượng có thể có một thuộc tính trừu tượng, thuộc tính này sẽ được triển khai trong lớp dẫn xuất. Chương trình sau đây minh họa điều này -
using System;
namespace tutorialspoint {
public abstract class Person {
public abstract string Name {
get;
set;
}
public abstract int Age {
get;
set;
}
}
class Student : Person {
private string code = "N.A";
private string name = "N.A";
private int age = 0;
// Declare a Code property of type string:
public string Code {
get {
return code;
}
set {
code = value;
}
}
// Declare a Name property of type string:
public override string Name {
get {
return name;
}
set {
name = value;
}
}
// Declare a Age property of type int:
public override int Age {
get {
return age;
}
set {
age = value;
}
}
public override string ToString() {
return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
}
}
class ExampleDemo {
public static void Main() {
// Create a new Student object:
Student s = new Student();
// Setting code, name and the age of the student
s.Code = "001";
s.Name = "Zara";
s.Age = 9;
Console.WriteLine("Student Info:- {0}", s);
//let us increase age
s.Age += 1;
Console.WriteLine("Student Info:- {0}", s);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10
An indexercho phép một đối tượng được lập chỉ mục chẳng hạn như một mảng. Khi bạn xác định một chỉ mục cho một lớp, lớp này hoạt động tương tự nhưvirtual array. Sau đó, bạn có thể truy cập cá thể của lớp này bằng toán tử truy cập mảng ([]).
Cú pháp
Trình lập chỉ mục một chiều có cú pháp sau:
element-type this[int index] {
// The get accessor.
get {
// return the value specified by index
}
// The set accessor.
set {
// set the value specified by index
}
}
Sử dụng trình chỉ mục
Tuyên bố về hành vi của người lập chỉ mục ở một mức độ nào đó tương tự như một thuộc tính. tương tự như các thuộc tính, bạn sử dụng get và setngười truy cập để xác định một trình chỉ mục. Tuy nhiên, các thuộc tính trả về hoặc thiết lập một thành viên dữ liệu cụ thể, trong khi các chỉ mục trả về hoặc đặt một giá trị cụ thể từ cá thể đối tượng. Nói cách khác, nó chia dữ liệu cá thể thành các phần nhỏ hơn và lập chỉ mục từng phần, lấy hoặc đặt từng phần.
Việc xác định thuộc tính liên quan đến việc cung cấp tên tài sản. Các chỉ mục không được xác định bằng tên, nhưng vớithistừ khóa, đề cập đến cá thể đối tượng. Ví dụ sau thể hiện khái niệm -
using System;
namespace IndexerApplication {
class IndexedNames {
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames() {
for (int i = 0; i < size; i++)
namelist[i] = "N. A.";
}
public string this[int index] {
get {
string tmp;
if( index >= 0 && index <= size-1 ) {
tmp = namelist[index];
} else {
tmp = "";
}
return ( tmp );
}
set {
if( index >= 0 && index <= size-1 ) {
namelist[index] = value;
}
}
}
static void Main(string[] args) {
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for ( int i = 0; i < IndexedNames.size; i++ ) {
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
Trình lập chỉ mục bị quá tải
Các chỉ mục có thể bị quá tải. Các chỉ mục cũng có thể được khai báo với nhiều tham số và mỗi tham số có thể là một kiểu khác nhau. Không nhất thiết các chỉ mục phải là số nguyên. C # cho phép các chỉ mục thuộc các kiểu khác, ví dụ, một chuỗi.
Ví dụ sau minh họa các trình chỉ mục bị quá tải:
using System;
namespace IndexerApplication {
class IndexedNames {
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames() {
for (int i = 0; i < size; i++) {
namelist[i] = "N. A.";
}
}
public string this[int index] {
get {
string tmp;
if( index >= 0 && index <= size-1 ) {
tmp = namelist[index];
} else {
tmp = "";
}
return ( tmp );
}
set {
if( index >= 0 && index <= size-1 ) {
namelist[index] = value;
}
}
}
public int this[string name] {
get {
int index = 0;
while(index < size) {
if (namelist[index] == name) {
return index;
}
index++;
}
return index;
}
}
static void Main(string[] args) {
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
//using the first indexer with int parameter
for (int i = 0; i < IndexedNames.size; i++) {
Console.WriteLine(names[i]);
}
//using the second indexer with the string parameter
Console.WriteLine(names["Nuha"]);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
2
Các đại biểu của C # tương tự như con trỏ đến các hàm, trong C hoặc C ++. Adelegatelà một biến kiểu tham chiếu chứa tham chiếu đến một phương thức. Tham chiếu có thể được thay đổi trong thời gian chạy.
Các đại biểu đặc biệt được sử dụng để triển khai các sự kiện và các phương thức gọi lại. Tất cả các đại biểu được hoàn toàn bắt nguồn từSystem.Delegate lớp học.
Tuyên bố đại biểu
Khai báo ủy quyền xác định các phương thức có thể được tham chiếu bởi ủy quyền. Một đại biểu có thể tham chiếu đến một phương thức có cùng chữ ký với của đại biểu.
Ví dụ, hãy xem xét một đại biểu -
public delegate int MyDelegate (string s);
Đại biểu đứng trước có thể được sử dụng để tham chiếu bất kỳ phương thức nào có tham số chuỗi đơn và trả về một biến kiểu int .
Cú pháp khai báo ủy quyền là:
delegate <return type> <delegate-name> <parameter list>
Khởi tạo đại biểu
Khi một kiểu ủy quyền được khai báo, một đối tượng ủy quyền phải được tạo với new từ khóa và được liên kết với một phương pháp cụ thể. Khi tạo một đại biểu, đối số được chuyển đếnnewbiểu thức được viết tương tự như một lời gọi phương thức, nhưng không có đối số của phương thức. Ví dụ -
public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
Ví dụ sau minh họa khai báo, khởi tạo và sử dụng một đại diện có thể được sử dụng để tham chiếu các phương thức nhận tham số số nguyên và trả về giá trị số nguyên.
using System;
delegate int NumberChanger(int n);
namespace DelegateAppl {
class TestDelegate {
static int num = 10;
public static int AddNum(int p) {
num += p;
return num;
}
public static int MultNum(int q) {
num *= q;
return num;
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
//create delegate instances
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
//calling the methods using the delegate objects
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of Num: 35
Value of Num: 175
Nhiều người đại diện
Các đối tượng ủy nhiệm có thể được tạo bằng cách sử dụng toán tử "+". Một đại biểu sáng tác gọi hai đại biểu mà nó được soạn từ. Chỉ các đại biểu cùng loại mới có thể được thành lập. Toán tử "-" có thể được sử dụng để xóa một đại biểu thành phần khỏi một đại biểu đã cấu thành.
Sử dụng thuộc tính này của các đại diện, bạn có thể tạo một danh sách gọi các phương thức sẽ được gọi khi một đại biểu được gọi. Đây được gọi làmulticastingcủa một đại biểu. Chương trình sau đây thể hiện đa hướng của một đại biểu:
using System;
delegate int NumberChanger(int n);
namespace DelegateAppl {
class TestDelegate {
static int num = 10;
public static int AddNum(int p) {
num += p;
return num;
}
public static int MultNum(int q) {
num *= q;
return num;
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
//create delegate instances
NumberChanger nc;
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc = nc1;
nc += nc2;
//calling multicast
nc(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of Num: 75
Sử dụng đại biểu
Ví dụ sau minh họa việc sử dụng đại biểu. Chuỗi printString của đại biểu có thể được sử dụng để tham chiếu phương thức lấy một chuỗi làm đầu vào và không trả về gì.
Chúng tôi sử dụng đại diện này để gọi hai phương thức, phương thức đầu tiên in chuỗi ra bảng điều khiển và phương thức thứ hai in ra tệp -
using System;
using System.IO;
namespace DelegateAppl {
class PrintString {
static FileStream fs;
static StreamWriter sw;
// delegate declaration
public delegate void printString(string s);
// this method prints to the console
public static void WriteToScreen(string str) {
Console.WriteLine("The String is: {0}", str);
}
//this method prints to a file
public static void WriteToFile(string s) {
fs = new FileStream("c:\\message.txt",
FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs);
sw.WriteLine(s);
sw.Flush();
sw.Close();
fs.Close();
}
// this method takes the delegate as parameter and uses it to
// call the methods as required
public static void sendString(printString ps) {
ps("Hello World");
}
static void Main(string[] args) {
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);
sendString(ps1);
sendString(ps2);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
The String is: Hello World
Eventslà các hành động của người dùng như nhấn phím, nhấp chuột, di chuyển chuột, v.v. hoặc một số trường hợp xảy ra như thông báo do hệ thống tạo. Các ứng dụng cần phản hồi các sự kiện khi chúng xảy ra. Ví dụ, ngắt. Sự kiện được sử dụng để giao tiếp giữa các quá trình.
Sử dụng đại biểu với sự kiện
Các sự kiện được khai báo và nâng lên trong một lớp và được liên kết với các trình xử lý sự kiện bằng cách sử dụng các đại biểu trong cùng một lớp hoặc một số lớp khác. Lớp chứa sự kiện được sử dụng để xuất bản sự kiện. Đây được gọi làpublisherlớp học. Một số lớp khác chấp nhận sự kiện này được gọi làsubscriber lớp học. Sự kiện sử dụngpublisher-subscriber mô hình.
A publisherlà một đối tượng chứa định nghĩa của sự kiện và đại biểu. Hiệp hội đại biểu sự kiện cũng được định nghĩa trong đối tượng này. Một đối tượng lớp nhà xuất bản gọi sự kiện và nó được thông báo cho các đối tượng khác.
A subscriberlà một đối tượng chấp nhận sự kiện và cung cấp một trình xử lý sự kiện. Đại biểu trong lớp nhà xuất bản gọi phương thức (trình xử lý sự kiện) của lớp thuê bao.
Khai báo sự kiện
Để khai báo một sự kiện bên trong một lớp, trước hết, bạn phải khai báo kiểu đại biểu cho chẵn như:
public delegate string BoilerLogHandler(string str);
sau đó, khai báo sự kiện bằng cách sử dụng event từ khóa -
event BoilerLogHandler BoilerEventLog;
Đoạn mã trước đó xác định một đại biểu có tên BoilerLogHandler và một sự kiện có tên BoilerEventLog , sự kiện này sẽ gọi đại biểu khi nó được nâng lên.
Thí dụ
using System;
namespace SampleApp {
public delegate string MyDel(string str);
class EventProgram {
event MyDel MyEvent;
public EventProgram() {
this.MyEvent += new MyDel(this.WelcomeUser);
}
public string WelcomeUser(string username) {
return "Welcome " + username;
}
static void Main(string[] args) {
EventProgram obj1 = new EventProgram();
string result = obj1.MyEvent("Tutorials Point");
Console.WriteLine(result);
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Welcome Tutorials Point
Các lớp tập hợp là các lớp chuyên biệt để lưu trữ và truy xuất dữ liệu. Các lớp này cung cấp hỗ trợ cho ngăn xếp, hàng đợi, danh sách và bảng băm. Hầu hết các lớp bộ sưu tập thực hiện các giao diện giống nhau.
Các lớp tập hợp phục vụ nhiều mục đích khác nhau, chẳng hạn như cấp phát bộ nhớ động cho các phần tử và truy cập danh sách các mục trên cơ sở một chỉ mục, v.v. Các lớp này tạo ra các tập hợp các đối tượng của lớp Đối tượng, là lớp cơ sở cho tất cả các kiểu dữ liệu trong C #.
Các loại bộ sưu tập khác nhau và cách sử dụng của chúng
Sau đây là các lớp thường được sử dụng khác nhau của System.Collectionkhông gian tên. Nhấp vào các liên kết sau để kiểm tra chi tiết của chúng.
Sr.No. | Class & Description và Useage |
---|---|
1 | Lập danh sách Nó đại diện cho bộ sưu tập có thứ tự của một đối tượng có thể indexed riêng lẻ. Về cơ bản nó là một sự thay thế cho một mảng. Tuy nhiên, không giống như mảng, bạn có thể thêm và xóa các mục khỏi danh sách tại một vị trí được chỉ định bằng cách sử dụngindexvà mảng tự động thay đổi kích thước. Nó cũng cho phép cấp phát bộ nhớ động, thêm, tìm kiếm và sắp xếp các mục trong danh sách. |
2 | Hashtable Nó sử dụng một key để truy cập các phần tử trong bộ sưu tập. Bảng băm được sử dụng khi bạn cần truy cập các phần tử bằng cách sử dụng khóa và bạn có thể xác định một giá trị khóa hữu ích. Mỗi mục trong bảng băm có mộtkey/valueđôi. Chìa khóa được sử dụng để truy cập các mục trong bộ sưu tập. |
3 | SortedList Nó sử dụng một key cũng như một index để truy cập các mục trong danh sách. Danh sách đã sắp xếp là sự kết hợp của một mảng và một bảng băm. Nó chứa một danh sách các mục có thể được truy cập bằng khóa hoặc chỉ mục. Nếu bạn truy cập các mục bằng chỉ mục, thì đó là ArrayList và nếu bạn truy cập các mục bằng khóa, thì đó là Hashtable. Bộ sưu tập các mục luôn được sắp xếp theo giá trị khóa. |
4 | Cây rơm Nó đại diện cho một last-in, first out bộ sưu tập của đối tượng. Nó được sử dụng khi bạn cần quyền truy cập cuối cùng vào, ra trước của các mục. Khi bạn thêm một mục trong danh sách, nó được gọi làpushing mục và khi bạn xóa nó, nó được gọi là popping mặt hàng. |
5 | Xếp hàng Nó đại diện cho một first-in, first out bộ sưu tập của đối tượng. Nó được sử dụng khi bạn cần quyền truy cập vào trước, ra trước của các mục. Khi bạn thêm một mục trong danh sách, nó được gọi làenqueue và khi bạn xóa một mục, nó được gọi là deque. |
6 | BitArray Nó đại diện cho một mảng binary representation sử dụng các giá trị 1 và 0. Nó được sử dụng khi bạn cần lưu trữ các bit nhưng không biết trước số lượng bit. Bạn có thể truy cập các mục từ bộ sưu tập BitArray bằng cách sử dụnginteger index, bắt đầu từ số không. |
Genericscho phép bạn xác định đặc tả kiểu dữ liệu của các phần tử lập trình trong một lớp hoặc một phương thức, cho đến khi nó thực sự được sử dụng trong chương trình. Nói cách khác, generics cho phép bạn viết một lớp hoặc phương thức có thể hoạt động với bất kỳ kiểu dữ liệu nào.
Bạn viết các đặc tả cho lớp hoặc phương thức, với các tham số thay thế cho kiểu dữ liệu. Khi trình biên dịch gặp một phương thức khởi tạo cho lớp hoặc một lệnh gọi hàm cho phương thức, nó sẽ tạo ra mã để xử lý kiểu dữ liệu cụ thể. Một ví dụ đơn giản sẽ giúp hiểu khái niệm -
using System;
using System.Collections.Generic;
namespace GenericApplication {
public class MyGenericArray<T> {
private T[] array;
public MyGenericArray(int size) {
array = new T[size + 1];
}
public T getItem(int index) {
return array[index];
}
public void setItem(int index, T value) {
array[index] = value;
}
}
class Tester {
static void Main(string[] args) {
//declaring an int array
MyGenericArray<int> intArray = new MyGenericArray<int>(5);
//setting values
for (int c = 0; c < 5; c++) {
intArray.setItem(c, c*5);
}
//retrieving the values
for (int c = 0; c < 5; c++) {
Console.Write(intArray.getItem(c) + " ");
}
Console.WriteLine();
//declaring a character array
MyGenericArray<char> charArray = new MyGenericArray<char>(5);
//setting values
for (int c = 0; c < 5; c++) {
charArray.setItem(c, (char)(c+97));
}
//retrieving the values
for (int c = 0; c< 5; c++) {
Console.Write(charArray.getItem(c) + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
0 5 10 15 20
a b c d e
Đặc điểm của Generics
Generics là một kỹ thuật làm phong phú thêm các chương trình của bạn theo những cách sau:
Nó giúp bạn tối đa hóa việc tái sử dụng mã, an toàn khi nhập và hiệu suất.
Bạn có thể tạo các lớp tập hợp chung. Thư viện lớp .NET Framework chứa một số lớp thu thập chung mới trong không gian tên System.Collections.Generic . Bạn có thể sử dụng các lớp tập hợp chung này thay vì các lớp tập hợp trong không gian tên System.Collections .
Bạn có thể tạo giao diện, lớp, phương thức, sự kiện và đại biểu chung của riêng mình.
Bạn có thể tạo các lớp chung bị ràng buộc để cho phép truy cập vào các phương thức trên các kiểu dữ liệu cụ thể.
Bạn có thể nhận được thông tin về các loại được sử dụng trong một loại dữ liệu chung tại thời điểm chạy bằng cách phản ánh.
Phương pháp chung
Trong ví dụ trước, chúng ta đã sử dụng một lớp chung chung; chúng ta có thể khai báo một phương thức chung với một tham số kiểu. Chương trình sau đây minh họa khái niệm -
using System;
using System.Collections.Generic;
namespace GenericMethodAppl {
class Program {
static void Swap<T>(ref T lhs, ref T rhs) {
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
static void Main(string[] args) {
int a, b;
char c, d;
a = 10;
b = 20;
c = 'I';
d = 'V';
//display values before swap:
Console.WriteLine("Int values before calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values before calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
//call swap
Swap<int>(ref a, ref b);
Swap<char>(ref c, ref d);
//display values after swap:
Console.WriteLine("Int values after calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values after calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I
Đại biểu Chung
Bạn có thể xác định một đại biểu chung với các tham số kiểu. Ví dụ -
delegate T NumberChanger<T>(T n);
Ví dụ sau cho thấy việc sử dụng đại biểu này:
using System;
using System.Collections.Generic;
delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl {
class TestDelegate {
static int num = 10;
public static int AddNum(int p) {
num += p;
return num;
}
public static int MultNum(int q) {
num *= q;
return num;
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
//create delegate instances
NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);
//calling the methods using the delegate objects
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Value of Num: 35
Value of Num: 175
Chúng tôi đã thảo luận rằng các đại biểu được sử dụng để tham chiếu bất kỳ phương thức nào có cùng chữ ký với chữ ký của đại biểu. Nói cách khác, bạn có thể gọi một phương thức có thể được tham chiếu bởi một đại biểu bằng cách sử dụng đối tượng đại biểu đó.
Anonymous methodscung cấp một kỹ thuật để chuyển một khối mã làm tham số ủy nhiệm. Các phương thức ẩn danh là các phương thức không có tên, chỉ có phần thân.
Bạn không cần chỉ định kiểu trả về trong một phương thức ẩn danh; nó được suy ra từ câu lệnh return bên trong thân phương thức.
Viết một phương pháp ẩn danh
Các phương thức ẩn danh được khai báo khi tạo cá thể ủy quyền, với delegatetừ khóa. Ví dụ,
delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
Khối mã Console.WriteLine ("Phương thức ẩn danh: {0}", x); là phần thân của phương thức ẩn danh.
Người ủy nhiệm có thể được gọi cả với các phương thức ẩn danh cũng như các phương thức được đặt tên theo cùng một cách, tức là bằng cách truyền các tham số phương thức cho đối tượng ủy nhiệm.
Ví dụ,
nc(10);
Thí dụ
Ví dụ sau thể hiện khái niệm -
using System;
delegate void NumberChanger(int n);
namespace DelegateAppl {
class TestDelegate {
static int num = 10;
public static void AddNum(int p) {
num += p;
Console.WriteLine("Named Method: {0}", num);
}
public static void MultNum(int q) {
num *= q;
Console.WriteLine("Named Method: {0}", num);
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
//create delegate instances using anonymous method
NumberChanger nc = delegate(int x) {
Console.WriteLine("Anonymous Method: {0}", x);
};
//calling the delegate using the anonymous method
nc(10);
//instantiating the delegate using the named methods
nc = new NumberChanger(AddNum);
//calling the delegate using the named methods
nc(5);
//instantiating the delegate using another named methods
nc = new NumberChanger(MultNum);
//calling the delegate using the named methods
nc(2);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Anonymous Method: 10
Named Method: 15
Named Method: 30
C # cho phép sử dụng các biến con trỏ trong một hàm của khối mã khi nó được đánh dấu bởi unsafebổ nghĩa. Cácunsafe code hoặc mã không được quản lý là một khối mã sử dụng pointer Biến đổi.
Note- Để thực thi các chương trình được đề cập trong chương này tại codingground , vui lòng đặt tùy chọn biên dịch trong Dự án >> Tùy chọn biên dịch >> Lệnh biên dịch thành
mcs *.cs -out:main.exe -unsafe"
Con trỏ
A pointerlà một biến có giá trị là địa chỉ của một biến khác tức là địa chỉ trực tiếp của vị trí bộ nhớ. tương tự với bất kỳ biến hoặc hằng nào, bạn phải khai báo một con trỏ trước khi có thể sử dụng nó để lưu trữ bất kỳ địa chỉ biến nào.
Dạng chung của khai báo con trỏ là:
type *var-name;
Sau đây là các khai báo con trỏ hợp lệ:
int *ip; /* pointer to an integer */
double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */
Ví dụ sau minh họa việc sử dụng con trỏ trong C #, sử dụng công cụ sửa đổi không an toàn:
using System;
namespace UnsafeCodeApplication {
class Program {
static unsafe void Main(string[] args) {
int var = 20;
int* p = &var;
Console.WriteLine("Data is: {0} ", var);
Console.WriteLine("Address is: {0}", (int)p);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Data is: 20
Address is: 99215364
Thay vì khai báo toàn bộ phương thức là không an toàn, bạn cũng có thể khai báo một phần của mã là không an toàn. Ví dụ trong phần sau đây cho thấy điều này.
Lấy giá trị dữ liệu bằng con trỏ
Bạn có thể truy xuất dữ liệu được lưu trữ tại vị trí được tham chiếu bởi biến con trỏ, sử dụng ToString()phương pháp. Ví dụ sau đây chứng minh điều này -
using System;
namespace UnsafeCodeApplication {
class Program {
public static void Main() {
unsafe {
int var = 20;
int* p = &var;
Console.WriteLine("Data is: {0} " , var);
Console.WriteLine("Data is: {0} " , p->ToString());
Console.WriteLine("Address is: {0} " , (int)p);
}
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Data is: 20
Data is: 20
Address is: 77128984
Chuyển con trỏ làm tham số cho phương thức
Bạn có thể truyền một biến con trỏ cho một phương thức dưới dạng tham số. Ví dụ sau minh họa điều này -
using System;
namespace UnsafeCodeApplication {
class TestPointer {
public unsafe void swap(int* p, int *q) {
int temp = *p;
*p = *q;
*q = temp;
}
public unsafe static void Main() {
TestPointer p = new TestPointer();
int var1 = 10;
int var2 = 20;
int* x = &var1;
int* y = &var2;
Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
p.swap(x, y);
Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Before Swap: var1: 10, var2: 20
After Swap: var1: 20, var2: 10
Truy cập các phần tử mảng bằng con trỏ
Trong C #, tên mảng và con trỏ đến kiểu dữ liệu giống với dữ liệu mảng, không cùng kiểu biến. Ví dụ, int * p và int [] p, không cùng kiểu. Bạn có thể tăng biến con trỏ p vì nó không cố định trong bộ nhớ nhưng địa chỉ mảng được cố định trong bộ nhớ và bạn không thể tăng giá trị đó.
Do đó, nếu bạn cần truy cập dữ liệu mảng bằng biến con trỏ, như chúng ta thường làm trong C hoặc C ++ (vui lòng kiểm tra: C Pointers ), bạn cần sửa con trỏ bằng cách sử dụngfixed từ khóa.
Ví dụ sau đây chứng minh điều này -
using System;
namespace UnsafeCodeApplication {
class TestPointer {
public unsafe static void Main() {
int[] list = {10, 100, 200};
fixed(int *ptr = list)
/* let us have array address in pointer */
for ( int i = 0; i < 3; i++) {
Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
}
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200
Biên dịch mã không an toàn
Để biên dịch mã không an toàn, bạn phải chỉ định /unsafe chuyển đổi dòng lệnh với trình biên dịch dòng lệnh.
Ví dụ: để biên dịch một chương trình có tên prog1.cs có chứa mã không an toàn, từ dòng lệnh, hãy đưa ra lệnh:
csc /unsafe prog1.cs
Nếu bạn đang sử dụng Visual Studio IDE thì bạn cần kích hoạt sử dụng mã không an toàn trong thuộc tính dự án.
Để làm điều này -
Mở project properties bằng cách nhấp đúp vào nút thuộc tính trong Trình khám phá giải pháp.
Bấm vào Build chuyển hướng.
Chọn tùy chọn "Allow unsafe code".
A threadđược định nghĩa là đường dẫn thực thi của một chương trình. Mỗi luồng xác định một luồng điều khiển duy nhất. Nếu ứng dụng của bạn liên quan đến các hoạt động phức tạp và tốn thời gian, thì thường hữu ích khi đặt các đường dẫn hoặc luồng thực thi khác nhau, với mỗi luồng thực hiện một công việc cụ thể.
Chủ đề là lightweight processes. Một ví dụ phổ biến của việc sử dụng luồng là thực hiện lập trình đồng thời bởi các hệ điều hành hiện đại. Sử dụng các luồng giúp tiết kiệm lãng phí chu kỳ CPU và tăng hiệu quả của một ứng dụng.
Cho đến nay, chúng tôi đã viết các chương trình trong đó một luồng chạy như một quy trình duy nhất là phiên bản đang chạy của ứng dụng. Tuy nhiên, bằng cách này, ứng dụng có thể thực hiện từng công việc một. Để làm cho nó thực thi nhiều hơn một tác vụ cùng một lúc, nó có thể được chia thành các luồng nhỏ hơn.
Vòng đời của chuỗi
Vòng đời của một luồng bắt đầu khi một đối tượng của lớp System.Threading.Thread được tạo và kết thúc khi luồng được kết thúc hoặc hoàn thành việc thực thi.
Sau đây là các trạng thái khác nhau trong vòng đời của một luồng:
The Unstarted State - Đó là tình huống khi thể hiện của luồng được tạo nhưng phương thức Start không được gọi.
The Ready State - Là tình trạng luồng sẵn sàng chạy và chờ chu kỳ CPU.
The Not Runnable State - Một luồng không thực thi được, khi
- Phương pháp ngủ đã được gọi là
- Phương thức chờ đã được gọi
- Bị chặn bởi các hoạt động I / O
The Dead State - Đó là tình huống khi luồng hoàn thành thực thi hoặc bị hủy bỏ.
Chủ đề chính
Trong C #, System.Threading.Threadlớp được sử dụng để làm việc với các luồng. Nó cho phép tạo và truy cập các luồng riêng lẻ trong một ứng dụng đa luồng. Luồng đầu tiên được thực thi trong một quy trình được gọi làmain sợi chỉ.
Khi chương trình C # bắt đầu thực thi, luồng chính sẽ tự động được tạo. Các chủ đề được tạo bằng cách sử dụngThreadlớp được gọi là các luồng con của luồng chính. Bạn có thể truy cập một chuỗi bằng cách sử dụngCurrentThread thuộc tính của lớp Thread.
Chương trình sau minh họa việc thực thi luồng chính:
using System;
using System.Threading;
namespace MultithreadingApplication {
class MainThreadProgram {
static void Main(string[] args) {
Thread th = Thread.CurrentThread;
th.Name = "MainThread";
Console.WriteLine("This is {0}", th.Name);
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
This is MainThread
Thuộc tính và phương thức của lớp chủ đề
Bảng sau đây cho thấy một số properties sau đó Thread lớp học -
Sr.No. | Kê khai tài sản |
---|---|
1 | CurrentContext Nhận ngữ cảnh hiện tại mà luồng đang thực thi. |
2 | CurrentCulture Lấy hoặc đặt văn hóa cho luồng hiện tại. |
3 | CurrentPrinciple Nhận hoặc thiết lập chính hiện tại của luồng (để bảo mật dựa trên vai trò). |
4 | CurrentThread Nhận luồng hiện đang chạy. |
5 | CurrentUICulture Lấy hoặc đặt văn hóa hiện tại được Người quản lý tài nguyên sử dụng để tra cứu các tài nguyên dành riêng cho văn hóa tại thời điểm chạy. |
6 | ExecutionContext Nhận đối tượng ExecutionContext chứa thông tin về các ngữ cảnh khác nhau của luồng hiện tại. |
7 | IsAlive Nhận giá trị cho biết trạng thái thực thi của luồng hiện tại. |
số 8 | IsBackground Nhận hoặc đặt một giá trị cho biết một luồng có phải là một luồng nền hay không. |
9 | IsThreadPoolThread Nhận một giá trị cho biết một luồng có thuộc nhóm luồng được quản lý hay không. |
10 | ManagedThreadId Nhận số nhận dạng duy nhất cho chuỗi được quản lý hiện tại. |
11 | Name Lấy hoặc đặt tên của chủ đề. |
12 | Priority Nhận hoặc đặt một giá trị cho biết mức độ ưu tiên lập lịch của một luồng. |
13 | ThreadState Nhận một giá trị chứa các trạng thái của luồng hiện tại. |
Bảng sau đây cho thấy một số methods sau đó Thread lớp học -
Sr.No. | Phương pháp & Mô tả |
---|---|
1 | public void Abort() Tăng một ThreadAbortException trong luồng mà nó được gọi, để bắt đầu quá trình kết thúc luồng. Gọi phương thức này thường kết thúc luồng. |
2 | public static LocalDataStoreSlot AllocateDataSlot() Phân bổ một vùng dữ liệu không tên trên tất cả các chuỗi. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute thay thế. |
3 | public static LocalDataStoreSlot AllocateNamedDataSlot(string name) Phân bổ một vùng dữ liệu được đặt tên trên tất cả các luồng. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute thay thế. |
4 | public static void BeginCriticalRegion() Thông báo cho máy chủ lưu trữ rằng việc thực thi sắp nhập vào một vùng mã mà các tác động của việc hủy bỏ luồng hoặc ngoại lệ chưa được xử lý có thể gây nguy hiểm cho các tác vụ khác trong miền ứng dụng. |
5 | public static void BeginThreadAffinity() Thông báo cho máy chủ lưu trữ rằng mã được quản lý sắp thực thi các lệnh phụ thuộc vào danh tính của luồng hệ điều hành vật lý hiện tại. |
6 | public static void EndCriticalRegion() Thông báo cho máy chủ lưu trữ rằng việc thực thi sắp nhập vào một vùng mã trong đó các tác động của việc hủy bỏ luồng hoặc ngoại lệ chưa được xử lý bị giới hạn cho tác vụ hiện tại. |
7 | public static void EndThreadAffinity() Thông báo cho máy chủ lưu trữ rằng mã được quản lý đã hoàn thành việc thực thi các hướng dẫn phụ thuộc vào danh tính của luồng hệ điều hành vật lý hiện tại. |
số 8 | public static void FreeNamedDataSlot(string name) Loại bỏ mối liên kết giữa tên và vị trí cho tất cả các luồng trong quy trình. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute thay thế. |
9 | public static Object GetData(LocalDataStoreSlot slot) Lấy giá trị từ vị trí được chỉ định trên luồng hiện tại, trong miền hiện tại của luồng hiện tại. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. |
10 | public static AppDomain GetDomain() Trả về miền hiện tại mà chuỗi hiện tại đang chạy. |
11 | public static AppDomain GetDomainID() Trả về một mã định danh miền ứng dụng duy nhất |
12 | public static LocalDataStoreSlot GetNamedDataSlot(string name) Tìm kiếm vùng dữ liệu được đặt tên. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute thay thế. |
13 | public void Interrupt() Ngắt một chuỗi đang ở trạng thái chuỗi WaitSleepJoin. |
14 | public void Join() Chặn luồng gọi cho đến khi một luồng kết thúc, trong khi tiếp tục thực hiện bơm COM và SendMessage tiêu chuẩn. Phương thức này có các dạng nạp chồng khác nhau. |
15 | public static void MemoryBarrier() Đồng bộ hóa quyền truy cập bộ nhớ như sau: Bộ xử lý thực hiện luồng hiện tại không thể sắp xếp lại thứ tự các lệnh theo cách mà bộ nhớ truy cập trước khi lệnh gọi đến MemoryBarrier thực thi sau khi truy cập bộ nhớ theo lệnh gọi tới MemoryBarrier. |
16 | public static void ResetAbort() Hủy bỏ yêu cầu hủy bỏ cho chuỗi hiện tại. |
17 | public static void SetData(LocalDataStoreSlot slot, Object data) Đặt dữ liệu trong vị trí được chỉ định trên luồng hiện đang chạy, cho miền hiện tại của luồng đó. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute để thay thế. |
18 | public void Start() Bắt đầu một chủ đề. |
19 | public static void Sleep(int millisecondsTimeout) Làm cho chuỗi tạm dừng trong một khoảng thời gian. |
20 | public static void SpinWait(int iterations) Làm cho một chuỗi phải đợi số lần được xác định bởi tham số lặp |
21 | public static byte VolatileRead(ref byte address) public static double VolatileRead(ref double address) public static int VolatileRead(ref int address) public static Object VolatileRead(ref Object address) Đọc giá trị của một trường. Giá trị là giá trị mới nhất được ghi bởi bất kỳ bộ xử lý nào trong máy tính, bất kể số lượng bộ xử lý hoặc trạng thái bộ nhớ cache của bộ xử lý. Phương thức này có các dạng nạp chồng khác nhau. Chỉ một số được đưa ra ở trên. |
22 | public static void VolatileWrite(ref byte address,byte value) public static void VolatileWrite(ref double address, double value) public static void VolatileWrite(ref int address, int value) public static void VolatileWrite(ref Object address, Object value) Ghi giá trị vào một trường ngay lập tức để giá trị này hiển thị cho tất cả các bộ xử lý trong máy tính. Phương thức này có các dạng nạp chồng khác nhau. Chỉ một số được đưa ra ở trên. |
23 | public static bool Yield() Làm cho luồng đang gọi nhường quyền thực thi cho một luồng khác đã sẵn sàng chạy trên bộ xử lý hiện tại. Hệ điều hành chọn luồng để nhường. |
Tạo chủ đề
Các luồng được tạo bằng cách mở rộng lớp Thread. Sau đó, lớp Thread mở rộng sẽ gọiStart() để bắt đầu thực thi luồng con.
Chương trình sau đây thể hiện khái niệm -
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
Console.WriteLine("Child thread starts");
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main: Creating the Child thread
Child thread starts
Quản lý chuỗi
Lớp Thread cung cấp nhiều phương thức khác nhau để quản lý các luồng.
Ví dụ sau minh họa việc sử dụng sleep() phương pháp để tạm dừng luồng trong một khoảng thời gian cụ thể.
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
Console.WriteLine("Child thread starts");
// the thread is paused for 5000 milliseconds
int sleepfor = 5000;
Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000);
Thread.Sleep(sleepfor);
Console.WriteLine("Child thread resumes");
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes
Phá hủy chủ đề
Các Abort() phương thức được sử dụng để hủy các chủ đề.
Thời gian chạy hủy chuỗi bằng cách ném ThreadAbortException. Không thể bắt được ngoại lệ này, điều khiển được gửi đến khối cuối cùng , nếu có.
Chương trình sau đây minh họa điều này -
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
try {
Console.WriteLine("Child thread starts");
// do some work, like counting to 10
for (int counter = 0; counter <= 10; counter++) {
Thread.Sleep(500);
Console.WriteLine(counter);
}
Console.WriteLine("Child Thread Completed");
} catch (ThreadAbortException e) {
Console.WriteLine("Thread Abort Exception");
} finally {
Console.WriteLine("Couldn't catch the Thread Exception");
}
}
static void Main(string[] args) {
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
//stop the main thread for some time
Thread.Sleep(2000);
//now abort the child
Console.WriteLine("In Main: Aborting the Child thread");
childThread.Abort();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception