Cập nhật thông tin chi tiết về Sử Dụng Delegate Trong C# Hàm Ủy Quyền mới nhất trên website Tvzoneplus.com. Hy vọng nội dung bài viết sẽ đáp ứng được nhu cầu của bạn, chúng tôi sẽ thường xuyên cập nhật mới nội dung để bạn nhận được thông tin nhanh chóng và chính xác nhất.
Giới thiệu delegate
Delegate ( hàm ủy quyền) là một kiểu dữ liệu, nó dùng để tham chiếu (trỏ đến) đến các hàm (phương thức) có tham số và kiểu trả về phù hợp với khai báo kiểu. Khi dùng đến delegate bạn có thể gán vào nó một, nhiều hàm (phương thức) có sự tương thích về tham số, kiểu trả về, sau đó dùng nó để gọi hàm(giống con trỏ trong C++), các event trong C# chính là các hàm được gọi thông qua delegate, bạn cũng có thể dùng delegate để xây dựng các hàm callback, đặc biệt là các Event
Delegate được dùng phổ biến khi gán các biểu thức lambda
Ví dụ sử dụng delegate
1 Đầu tiên cần khai báo một delegate, khai báo giống như cách khai báo phương thức nhưng có thêm từ khóa delegate và không có thân phương thức. Ví dụ sau khai báo một delegate có tên là ShowLog
public delegate void ShowLog(string message);2 Khi đã có ShowLog, nó dùng như một kiểu dữ liệu để khai báo các biến, các biến này có thể gán vào nó các hàm có sự tương đồng về tham số và kiểu trả về với khai báo delegate ví dụ khai báo biến:
ShowLog showLog;Thi hành delegate
Sau khi biến delegate được gán hàm vào, có thể dùng biến delegate để thi hành bằng cách gọi: varDelegate.Invoke(các-tham-số) hoặc varDelegate(các-tham-số)
3 Tạo hai phương thức Info và Warning có tham số giống với ShowLog, nghĩa là có một tham số kiểu string, trả về void:
static public void Info(string s) { } static public void Warning(string s) { }Do Info, Warning có tương đồng về tham số với delegate trên, nên hai hàm này có thể dùng để gán vào biến kiểu ShowLog, xem đoạn mã đầy đủ sau:
Logs.cs
using System; namespace CS008_Anonymous { public class Logs { public delegate void ShowLog(string message); static public void Info(string s) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(string.Format("Info: {0}", s)); Console.ResetColor(); } static public void Warning(string s) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(string.Format("Waring: {0}", s)); Console.ResetColor(); } public static void TestShowLog() { ShowLog showLog; showLog = Info; showLog("Thông báo"); showLog = Warning; showLog("Thông báo"); } } }Kết quả chạy đoạn, khi gọi hàm Logs.TestShowLog();:
Waring: Thông báo Info: Thông báoGán nhiều phương thức vào delegate
Khi dùng delegate chạy một phương thức, cần đảm bảo biến delegate đó đã được gán phương thức (biến khác null), có thể bạn kiểm tra trước khi gọi ví dụ: if (showLog != null) showLog("Mgs") hoặc gắn gọn hơn showLog?.Invoke("Mgs");
4 Một delegate có thể đưa vào nó nhiều phương thức để một lần gọi thi hành tất cả các phương thức nó chứa
Nối thêm một phương thức vào delegate, ví dụ delegatevar += method1
: Loại bỏ 1 phương ở cuối (nếu phương thức đó có trong delegate, tính từ cuối) , ví dụdelegatevar -= method1
Ví dụ:
public static void TestShowLogMulti() { ShowLog showLog; showLog = null; showLog += Warning; showLog += Info; showLog += Warning; showLog("TestLog"); }Gọi phương thức TestShowLogMulti thì kết quả:
Waring: TestLog Info: TestLog Waring: TestLog5 Ngoài cách gán cho delegate một hàm có tên cụ thể như trên, bạn cũng có thể gán một phương thức Anonymou, ví dụ:
6 Các delegate cùng kiểu có thể kết hợp lại với nhau bằng toán tử +, ví dụ:
public static void TestShowLogPlus() { ShowLog showLog2 = Warning; ShowLog showLog3 = Info; var all = showLog1 + showLog2 + showLog3 + showLog1; all("Xin Chào"); }Gọi phương thức TestShowLogPlus kết quả là:
-----Xin Chào----- Waring: Xin Chào Info: Xin Chào -----Xin Chào-----Func và Action
Func và Action là hai mẫu delegate định nghĩa sẵn, giúp bạn nhanh chóng tạo ra biến kiểu delegate mà không mất công khai báo, xem lại ví dụ trên nếu sử dụng đến Func, Action thì không cần có dòng khai báo:
public delegate void ShowLog(string message);Sử dụng Func
Func là mẫu delegate có kiểu trả về. Để khai báo biến delegate dùng cú pháp như sau:
Kiểu cuối cùng trong khai báo Func là kiểu trả về của hàm, có thể thiếu tham số nhưng không được thiếu kiểu trả về
Ví dụ muốn có biến delegate tên bien1 tương đương với hàm có 2 tham số, tham số 1 kiểu int, tham số 2 kiểu string, và hàm trả về kiểu bool thì tạo biến đó như sau:
Khai báo trên nếu bạn dùng cách thông thường tương ứng với:
delegate bool DelegateName(int a, string b); DelegateName bien1;Ví dụ:
using System; namespace CS008_Anonymous { class FuncAction { static int Sum(int x, int y) { return x + y; } public static void TestFunc(int x, int y) { tinhtong = Sum; var ketqua = tinhtong(x, y); Console.WriteLine(ketqua); } } }Khi gọi phương thức TestFunc kết quả:
FuncAction.TestFunc(5, 6);Sử dụng Action
Action tương tự như Func, điều khác duy nhất là nó không có kiểu trả về, khai báo cơ bản như sau:
Nghĩa là biến kiểu Action có thể gán bằng các hàm có kiểu trả về void
Trở lại ví dụ cho hai hàm Info và Warning ở trên, có thể sử dụng ngay đoạn code sau, để có kết quả tương tự:
public static void TestAction(string s) { showLog += Logs.Warning; showLog += Logs.Info; showLog += Logs.Warning; showLog("TestLog"); }Sử dụng Delegate làm tham số hàm
Có thể sử dụng delegate làm tham số của phương thức, nó có vai trò như những hàm callback linh hoạt. Xem ví dụ sau:
Source code: CS008_Anonymous (Git), hoặc tải ex008-1
Biểu Thức Lambda Trong C# Sử Dụng Lambda Với Delegate
Khai báo lambda C#
{
Các biểu thức lambda đều có thể chuyển đổi thành delegate, do vậy nó có thể gán cho các delegate phù hợp – (bạn cần biết cách sử dụng delegate trước).
Sử dụng lambda C#
Ví dụ, đây là một biểu thức lambda, nó tính tổng của hai số nguyên
return x + y; };
Có thể gán biểu thức này cho biến delegate. Ví dụ:
using System; namespace CS09_Anonymous_lambda { class Program { public delegate int TinhToan (int a, int b); static void Main (string[] args) { return x + y; }; int kq = tinhtong (5, 1); Console.WriteLine(kq); } } }Như phần trình bày về Delegate, có thể gán biểu thức lambda có kết quả trả về cho Func hoặc biểu thức không có kết quả trả về cho Action
using System; namespace CS09_Anonymous_lambda { class Program { public delegate int TinhToan (int a, int b); static void Main (string[] args) { return x + y; }; Console.WriteLine (vl); }; int kq1 = tinhtong1 (5, 3); int kq2 = tinhtong1 (5, 5); thongbao (kq1); thongbao (kq2); } } }Định nghĩa phương thức với lambda
Ví dụ, khai báo phương thức:
Nó tương đương với dạng đầy đủ đã biết
int Tong(int x, int y) { return x + y; }Source code: CS009_Anonymous_lambda (Git), hoặc tải ex009
Nguyên Mẫu Hàm Trong C/C++ Là Gì? Và Cách Sử Dụng
Series lập trình C/C++, ngôn ngữ lập trình hệ thống mạnh mẽ.
Ở bài viết trước, chúng ta đã biết được khái niệm Hàm là gì và và cách sử dụng hàm trong lập trình C/C++. Trong bài viết này sẽ trình bày một trong những tính năng quan trọng khác của C/C++ là Nguyên mẫu hàm (Function Prototype).
Nguyên mẫu hàm là gì?
Cách khai báo và vị trí đặt của nguyên mẫu hàm.
Nguyên mẫu hàm được sử dụng khi nào?
Nguyên mẫu hàm (Function Prototype) cung cấp cho trình biên dịch (compiler) tên của hàm, kiểu dữ liệu mà hàm trả về, số lượng các tham số của hàm (gồm kiểu dữ liệu và thứ tự của các tham số đó). Nhờ đó, hàm nguyên mẫu giúp cho trình biên dịch xác nhận các lời gọi hàm mà chưa cần định nghĩa hàm đó.
2. Cách khai báo và vị trí đặt của nguyên mẫu hàm.
■ 1.Cách khai báo:
Kiểu_dữ_liệu_trả_về Tên_hàm(); Kiểu_dữ_liệu_trả_về Tên_hàm( Kiểu_dữ_liệu_1 tham_số_1, ..., Kiểu_dữ_liệu_n tham_số_n ); Kiểu_dữ_liệu_trả_về Tên_hàm( Kiểu_dữ_liệu_1, ..., Kiểu_dữ_liệu_n );Ví dụ: ・ TinhTong( int a, int b ); ・ TinhHieu( int, int ); ・ HoanVi( int &, int & ); ・ RemoveExtension( char *, bool );
■ 2.Vị trí đặt của nguyên mẫu hàm: Nguyên mẫu hàm khi khai báo cần phải được đặt trên/ đặt trước lời gọi hàm tức là trước hàm gọi nó thực hiện. (Xem ví dụ minh họa bên dưới)
3. Nguyên mẫu hàm được sử dụng khi nào?
・ Ở ví dụ của mục 4 trong bài viết Các bước viết một hàm trong C/C++, chúng ta thấy 2 hàm TinhTong va TinhHieu 2 số nguyên được đặt trên hàm main() (tức là hàm gọi) thì không cần khai báo nguyên mẫu hàm. Vì chương trình chạy từ trên xuống dưới thì trình biên dịch (compiler) đã nhận biết dc sự có mặt của 2 hàm này rồi, nên ở hàm main() có lời gọi hàm TinhTong, TinhHieu sẽ được thực hiện được bình thường.
・ Dùng nguyên mẫu hàm khi:
Hàm thực hiện chức năng được định nghĩa dưới hàm gọi nó.
Các hàm được tổ chức trong các file khác nhau.
■ chúng tôi hàm thực hiện chức năng ( TinhTong, TinhHieu) được định nghĩa dưới hàm (main) gọi nó.
int TinhTong(int a, int b); int TinhHieu(int, int); int main() { int a, b, tong, hieu; printf( "Nhap vao a = " ); scanf_s( "%d", &a ); printf( "Nhap vao b = " ); scanf_s( "%d", &b ); tong = TinhTong(a, b); printf("Tong cua 2 so la: %dn", tong); hieu = TinhHieu(a, b); printf("Hieu cua 2 so la: %dn", hieu); getchar(); return 0; } int TinhTong(int a, int b) { return a + b; } int TinhHieu(int a, int b) { return a - b; }■ chúng tôi các hàm được tổ chức trong các file khác nhau, có nghĩa là mỗi hàm sẽ được viết trong từng file riêng biệt. Ví dụ các file trong chương trình được tổ chức như hình bên dưới:
– Trong đó:
File NguyenMauHam.h : Khai báo các nguyên mẫu hàm
File TinhTong.c : chứa định nghĩa của hàm tính tổng 2 số
File TinhHieu.c : chứa định nghĩa của hàm tính hiệu 2 số
File Main.c : hàm main() thực hiện chương trình
– Nội dung của các file như sau:
★ File NguyenMauHam.h
#ifndef NGUYEN_MAU_HAM #define NGUYEN_MAU_HAM int TinhTong(int a, int b); int TinhHieu(int, int); #endif★ File TinhTong.c
#include "NguyenMauHam.h" int TinhTong(int a, int b) { return a + b; }★ File TinhHieu.c
#include "NguyenMauHam.h" int TinhHieu(int a, int b) { return a - b; }★ File Main.c
#include "NguyenMauHam.h" int main() { int a, b, tong, hieu; printf( "Nhap vao a = " ); scanf_s( "%d", &a ); printf( "Nhap vao b = " ); scanf_s( "%d", &b ); tong = TinhTong(a, b); printf("Tong cua 2 so la: %dn", tong); hieu = TinhHieu(a, b); printf("Hieu cua 2 so la: %dn", hieu); getchar(); return 0; }Sử Dụng Mảng Trong C++
Giới thiệu
Mảng dữ liệu là một tập hợp các phần tử có cùng kiểu dữ liệu và được truy cập thông qua index. Việc vận dụng mảng dữ liệu trong việc học tập và làm việc là điều không thể thiếu đối với mỗi lập trình viên. Bài viết này sẽ cung cấp cho những kiến thức cơ bản về mảng dữ liệu trong ngôn ngữ C++.
Đặt vấn đề
Khi cần lưu trữ một số lượng lớn các phần tử có cùng kiểu dữ liệu, chẳng hạn như cần lưu trữ 30 số nguyên được nhập từ bàn phím, có thể dùng 30 biến số nguyên riêng biệt để lưu trữ. Tuy nhiên, cách trên có một số nhược điểm như sau:
Có quá nhiều biến cần khởi tạo. Để nhớ được hết các biến này là không đơn giản, đồng thời gây khó khăn cho việc quản lý các biến.
Phải thực hiện thủ công các thao tác với biến đó. Do các biến là độc lập nên không thể sử dụng các cấu trúc lặp để thao tác với nó.
Chương trình sẽ dài và việc nâng cấp cũng trở nên khó khăn.
Do đó, việc nhóm các phần tử đó lại với một cái tên duy nhất sẽ khắc phục được những nhược điểm trên. Các phần tử vẫn hoạt động độc lập, nhưng dưới một tên duy nhất, cùng với chỉ số (index) của nó để phân biệt với các phần tử khác.
Khai báo và sử dụng mảng
Cú pháp khai báo mảng như sau:
Kiểu dữ liệu của mảng sẽ quy định kiểu dữ liệu của các phần tử có trong mảng. Tên mảng được đặt tên theo quy tắc đặt tên biến trong C/C++. Khi đó, hệ thống sẽ tìm một vùng nhớ liên tiếp phù hợp để cấp phát cho biến mảng. Lưu ý, số lượng phần tử phải là 1 HẰNG SỐ .
Index phần tử đầu tiên là 0. Nên khai báo mảng n phần tử thì index của phần tử cuối cùng là . Điều này cũng đúng cho rất nhiều ngôn ngữ lập trình thông dụng hiện nay.
Ngoài cách khai báo trên, C++ còn cho phép lập trình viên khai báo không tường minh, khai báo và khởi tạo giá trị ban đầu cho các phần tử.
int main() { int a[10]; for(int i = 0; i < 10; i++) { scanf("%d", &a[i]); } for(int i = 0; i < 10; i++) { printf("%d ", a[i]); } printf("n"); int b[10] = {7, 4, 1, 1}; for(int i = 0; i < 10; i++) { printf("%d ", *(b + i)); } printf("n"); char str [] = "Welcome to STDIO"; printf("%d", strlen(str)); return 0; }Mảng nhiều chiều
Khi mỗi phần tử của mảng có kiểu dữ liệu là một mảng khác thì được mảng 2 chiều. Khi đó, ngoài index của các phần tử trong mảng, mỗi phần tử trong các phần tử đó cũng có index của nó. Do đó để truy xuất đến từng phần tử nhỏ, sử dụng cả 2 chỉ số index để chỉ ra vị trí của nó trong mảng 2 chiều.
Xem ví dụ sau để nắm được cách khai báo và sử dụng mảng 2 chiều.
int main() { int a[3][3]; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { scanf(“%d”, &a[i][j]); } } for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { printf(“%d “, a[i][j]); } printf(“n”); }
int b[3][3] = {{1, 3}, {2, 4, 6}}; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { printf(“%d “, b[i][j]); } printf(“n”); }
return 0; }
Truyền tham chiếu mảng vào hàm
void Function1(int a[]) { } void Function2(int a[][10]) { }Đối với mảng động được cấp phát cho con trỏ, thao tác như sau:
void Function3(int *&a, int n) { }Bạn đang xem bài viết Sử Dụng Delegate Trong C# Hàm Ủy Quyền trên website Tvzoneplus.com. Hy vọng những thông tin mà chúng tôi đã chia sẻ là hữu ích với bạn. Nếu nội dung hay, ý nghĩa bạn hãy chia sẻ với bạn bè của mình và luôn theo dõi, ủng hộ chúng tôi để cập nhật những thông tin mới nhất. Chúc bạn một ngày tốt lành!