Tìm kiếm Blog này

Hiển thị các bài đăng có nhãn C#. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn C#. Hiển thị tất cả bài đăng

Chủ Nhật, 9 tháng 1, 2011

PHƯƠNG THỨC

1.   Khái niệm về method
Method (Tiếng việt gọi là hàm hoặc phương thức) là một thành phần của class dùng để thực thi một công việc nào đó của một đối tượng hoặc một class. Một method sẽ chứa một danh sách các đối số(hoặc có thể không có đối số), một giá trị trả về (trừ void method). Method có thể là static (tĩnh) hoặc non- static (hay là instance method- phương thức thể hiện). Đây là ví dụ về method:

public class Stack
{
            public static Stack Clone(Stack s) {...}
            public static Stack Flip(Stack s) {...}
            public object Pop() {...}
            public void Push(object o) {...}
            public override string ToString() {...}
            ...
}
class Test
{
            static void Main() {
                        Stack s = new Stack();
                        for (int i = 1; i < 10; i++)
                                    s.Push(i);
                        Stack flipped = Stack.Flip(s);
                        Stack cloned = Stack.Clone(s);
                        Console.WriteLine("Original stack: " + s.ToString());
                        Console.WriteLine("Flipped stack: " + flipped.ToString());
                        Console.WriteLine("Cloned stack: " + cloned.ToString());
            }
}
Class Stack có 2 phương thức tĩnh (static method) là Clone và Flip và các phương thức thể hiện là Push, PushPop, andToString. Một lần nữa bạn thấy các phương thức tĩnh được gọi trực tiếp từ tên của lớp còn phương thức thể hiện phải được gọi qua thể hiện của lớp. Phương thức có thể được overloaded .  Có nghĩa là nhiều methods có tên giống nhau. Bạn sẽ được học về overloading methods trong bài tới.



2.   Truyền tham số cho method




Việc truyền tham số vào cho phương thức chỉ được thực hiện đối với các kiểu dữ liệu giá trị. Vậy cách thức truyền tham số sẽ được thực hiện như thế nào? Trong C# các tham số được truyền vào hàm thông qua 2 cách là truyền theo giá trị (truyền tham trị) và truyền theo địa chỉ (truyền tham chiếu). Chúng ta sẽ lần lượt tìm hiểu hai các truyền này.



a.        Truyền tham trị

      Khi môt đối tượng có kiểu giá trị được truyền giá trị vào cho một phương thức thì có một bản sao chép đối tượng đó được tạo ra bên trong phương thức. Khi phương thức thực hiện xong thì đối tượng sao chép này sẽ được hủy.
Dưới đây là ví dụ về cách truyền tham trị:


using System;
public class Time
{
    public void DisplayCurrentTime()
    {
        Console.WriteLine("{0}/{1}/{2}/  {3}:{4}:{5}", Date,
            Month, Year, Hour, Minute, Second);
    }
    public int GetHour()
    {
        return Hour;
    }
    public void GetTime(int h, int m, int s)
    {
        h = Hour;
        m =  Minute;
        s = Second;
    }
    public Time( System.DateTime dt)
    {
        Year = dt.Year;
        Month = dt.Month;
        Date = dt.Day;
        Hour = dt.Hour;
        Minute = dt.Minute;
        Second = dt.Second;
    }
    private int Year;
    private int Month;
    private int Date;
    private int Hour;
    private int Minute;
    private int Second;
}
public class Tester
{
    static void Main()
    {
        System.DateTime currentTime = System.DateTime.Now;
        Time t = new Time( currentTime);
        t.DisplayCurrentTime();
        int theHour = 0;
        int theMinute = 0;
        int theSecond = 0;
        t.GetTime( theHour, theMinute, theSecond);
        System.Console.WriteLine("Current time: {0}:{1}:{2}",
        theHour, theMinute, theSecond);
    }
}


Kết quả:
8/6/2002  14:15:20
Current time: 0:0:0

Như các bạn thấy kết quả in ra Current time: 0:0:0 tức là các biến theHour, theMinute, theSecond vẫn giữ nguyên giá trị của nó sau hàm GetTime.

b.        Truyền tham chiếu

Như tôi đã nói trên, mỗi phương thức sẽ có một giá trị duy nhất được trả về, mặc dù giá trị này có thể là một tập hợp các giá trị. Đôi khi chúng ta muốn phương thức trả về nhiều hơn một giá trị. Cách thực hiện là tạo ra cách tham số dưới hình thức tham chiếu. Khi bạn truyền tham chiếu, trong phương thức bạn sẽ xử lý và gán các giá trị mới cho các tham chiếu này và kết quả là sau khi phương thức thực hiện xong ta dùng các tham số truyền vào như là các kết quả trả về. Để làm việc này bạn phải thêm từ khóa ref (viết tắt của reference) vào trước các tham số trong phần khai báo phương và lời gọi phương thức.
Ví dụ để các biến theHour, theMinute, theSecond trong ví dụ trên sau khi được xử lý trong GetTime sẽ có giá trị như chúng vừa được gán, chúng ta sẽ phải làm như sau:
Đầu tiên thêm khai báo ref vào trước các tham số trong phương thức GetTime():
public void GetTime(ref int h, ref int m, ref int s)
    {
        h = Hour;
        m = Minute;
        s = Second;
    }
Tiếp theo là sẽ gọi phương thức GetTime dưới dạng truyền tham chiếu như sau:

t.GetTime(ref theHour, ref theMinute, ref theSecond);

Tóm lại cơ chế truyền tham số dạng tham chiếu sẽ thực hiện trên chính đối tượng được đưa vào. Còn cơ chế truyền tham số giá trị thì sẽ tạo ra các bản sao các đối tượng được truyền vào, do đó mọi thay đổi bên trong phương thức không làm ảnh hưởng đến các đối tượng được truyền vào dưới dạng giá trị.

LỚP VÀ ĐỐI TƯỢNG

1.    Lớp và đối tượng


a.        Lớp (class)


      Một lớp là một khái niệm mô tả cho những thực thể có chung tính chất và hành vi. Lớp định nghĩa những thuộc tính và hành vi được dùng cho những đối tượng của lớp đó. Do đó có thể nói lớp là một khuôn mẫu cho các đối tượng.


Công thức để tạo một class

AccessModifier  class className
{
      // thân class
}

Ví dụ tôi định nghĩa một class là color, class này được truy cập public
public class Color
{
    // Nội dung class

}

b.         Đối tượng

Đối tượng là một đại diện, hay có thể nói là một sản phẩm của một class. Tất cả các đối tượng đều có chung những thuộc tính và hành vi mà class định nghĩa. Cách tạo đối tượng giống như cách tạo một biến có kiểu dữ liệu là Class.

Ví dụ tôi muốn khai báo một đối tượng c là thể hiện của class color nói trên. Tôi làm như sau:

       Color c = new Color();
Sau đó từ đối tượng c này tôi sẽ truy cập đến các thành phần của class thông qua toán tử “.” (Mà tôi đã giới thiệu ở bài học số 2). Tuy nhiên việc truy cập các thành phần của class còn tùy thuộc vào thành phần đó là instance hay static. Bạn sẽ được tìm hiểu khái niệm này ở phần tiếp theo của bài học.

c.         Ưu điểm khi sử dụng lớp và đối tượng trong lập trình

Có một số những ưu điểm của việc sử dụng Class và đối tượng trong phát triển phần mềm. Những ưu điểm nổi bật nhất được liệt kê như sau:

§         Duy trì code bằng việc mô hình hóa
§         Đóng gói những sự phức tạp trong mã lênh từ người dùng
§         Khả năng sử dụng lại
§         Cung cấp đơn kế thừa để thực thi nhiều phương thức.
Các bạn sẽ hiểu hơn về điều này ở các bài học sau của chúng tôi về inheritance (sự thừa kế) hay polymorphism ( Tính đa hình ).


2.    Khái niệm thành viên thể hiện (instance) và thành viên tĩnh(static)

Trong một lớp , các thành viên có thể là instance (thành viên thể hiện) hoặc static (thành   viên tĩnh). Một thành viên instance có nghĩa là thành viên đó liên quan đến thể hiện của một kiểu dữ liệu. Thành viên  static được xem như một phần của lớp. Chúng ta truy cập đến thành viên tĩnh của một lớp thông qua tên lớp đã được khai báo. Còn các thành viên instance thì phải thông qua thể hiện của lớp.
Giả sử chúng ta có một lớp là  class A và có 2 thể hiện là t1, t2 và một phương thức tĩnh là a(). Để truy cập phương thức này ta viết A.a(). Chứ không thể viết t1. a() hoặc t2.a() vì trong C# không cho phép truy cập đến phương thức cũng như các biến thành viên tĩnh thông qua một thể hiện.
Một số ngôn ngữ thì có sự phân chia giữa phương thức của lớp và các phương thức khác (toàn cục) tồn tại bên ngoài không phụ thuộc bất cứ một lớp nào. Tuy nhiên, điều này không cho phép trong C#, ngôn ngữ C# không cho phép tạo các phương thức bên ngoài của lớp, nhưng ta có thể tạo được các phương thức giống như  vậy bằng cách tạo các phương thức tĩnh bên trong một lớp. Phương thức tĩnh ít nhiều giống phương thức toàn cục bởi ta có thể truy cập đến nó không phải thông qua bất cứ một thể hiện nào của lớp chứa nó. Tuy nhiên phương thức tĩnh sẽ hoạt động tốt hơn phương thức toàn cục vì nó luôn được đặt trong phạm vi một lớp do đó chúng ta sẽ tránh được tình trạng lộn xộn do bị trùng tên giữa các phương thức đặt trong namespace.

3.    Các thành phần của lớp

a.         Fields


         Field là một phần tử dùng để thể hiện các biến trong  lớp – các  biến hoặc các thể hiện của một lớp dụ:

class Color
    {
        internal ushort redPart;
        internal ushort bluePart;
        internal ushort greenPart;
        public Color(ushort red, ushort blue, ushort green)
        {
            redPart = red;
            bluePart = blue;
            greenPart = green;
        }
    }    
Lớp color chứa các instance fields như là redPartbluePart, và greenPart.
     Fields có thể là static như ví dụ dưới đây:

      Class Color
      {
            public static Color Red = new Color(0xFF, 0, 0);
            public static Color Blue = new Color(0, 0xFF, 0);
            public static Color Green = new Color(0, 0, 0xFF);
            public static Color White = new Color(0xFF, 0xFF, 0xFF);
            ...
  }   
Các phần tử RedBlueGreenWhite đều là các phần tử static.

b.         Properties

Property (thuộc tính, đặc tính) là một phần tử dùng để truy cập đến đặc điểm của một đối tượng hoặc một class (lớp). Ví dụ  như là độ dài một chuỗi, kích cỡ của font chữ, độ rộng của một cửa sổ, tên của một customer …Property là phần mở rộng của fields. Cả 2 đều được gọi tên với các kiểu kết hợp, và cách truy cập đến fields và properties là như nhau. Tuy nhiên khác với fields, properties không chỉ rõ nới lưu trữ nó. Thay vào đó, properties có cách truy nhập là dùng câu lệnh để thi hành việc đọc và ghi giá trị.

Property được định nghĩa bằng 2 phần. Phần thứ nhất giống như cách định nghĩa Fields. Phần thứ 2 chứa phần tử truy cập get và set.  Các bạn hãy xem ví dụ dưới đây :

public class Button
      {
        private string caption;
        public string Caption
        {
            get
            {
                return caption;
            }
            set
            {
                caption = value;
                Repaint();
            }
        }
    }
c.         Methods 
         Bạn sẽ được học về methods ở bài sau

PHƯƠNG THỨC NẠP CHỒNG - OVERLOADING

C# hỗ trợ phương thức nạp chồng với một vài dạng phương thức khác nhau về những đặc tính sau: tên, số lượng thông số, và kiểu thông số. Nhưng nó không hỗ trợ những thông số mặc định như C++ và VB. Một cách đơn giản là bạn khai báo những phương thức cùng tên nhưng khác số lượng và kiểu của thông số.

Method Overloading xuất hiện khi trong một class có từ hai hàm có cùng tên. Có hai kiểu Method Overloading:

  • Function Overloading dựa trên kiểu giá trị tham số truyền vào.
  • Function Overloading dựa trên số lượng tham số truyền vào.

Ví dụ


class Library
{
// Function Overloading
        public void insertbooks(int id)
        {
            //
        }
        public void insertbooks(int id, int type)
        {
            //
        }
        public void insertbooks(string id, int type)
        {
            //
  }
}

Ba hàm insertbooks ở trên là một ví dụ về function overloading trong lập trình C#. Trong khi hàm thứ nhất và thứ 2 là overloading theo số lượng tham số, và hàm thứ 3 với hàm thứ 2 là overloading theo kiểu tham số truyền vào.



- Bởi vì C# không hỗ trợ những thông số tùy chọn nên bạn cần sử dụng những phương thức nạp chồng để đạt được cùng một hiệu quả:



class MyClass
{
   int DoSomething(int x) // Gọi hàm 2 tham số với một giá trị mặc định là 10;
  {
      DoSomething(x, 10);
  }

  int DoSomething(int x, int y)
  {
     // Làm một điều gì đó ở đây :D
  }
} 

- Trong bất kỳ một ngôn ngữ nào, phương thức nạp chồng có thể đem đến một lỗi nghiêm trọng nếu nó bị gọi sai. Trong chương tới ta sẽ bàn cách để tránh đều đó. Trong C# có một vài điểm khác nhỏ về thông số trong các phương thức nạp chồng cần biết như sau:
- Nó không chấp nhận hai phương thức chỉ khác nhau về kiểu trả về. 
- Nó không chấp nhận hai phương thức chỉ khác nhau về đặc tính của một thông số đang được khai báo như ref hay out.

CONSTRUCTOR & DESTRUCTOR

1.   Khái niệm về constructor và destructor

a.Constructor
Constructors (được gọi là hàm tạo) là những hàm đặc biệt cho phép thực thi, điều khiển chương trình ngay khi khởi tạo đối tượng. Trong C#, Constructors có tên giống như tên của Class và không có giá trị trả về.


     Ví dụ:


class Library
{
private int ibooktypes;
//Constructor
public Library() // Hàm tạo không đối số.
{
ibooktypes = 7;
}
public Library(int value)
          {
          ibooktypes = value;
          }
}



Ví dụ: Với dụ trên thì bạn có hai cách khởi tạo lớp Library thông qua một trong hai hàm tạo


  • Library lb1 = new Library()// Hàm tạo không đối số;
  •  Library lb2 = new Library(100); // Hàm tạo được truyền vào với giá trị là 100, và nó sẽ được gán vào ibooktypes = 100;

b.Destructor

Destructor (được gọi là hàm hủy) là một hàm dùng để hủy đi một thể hiện của một class. Destructor không có đối số, không có từ chỉ thuộc tính truy nhập, và không  được gọi tường minh. Destructor của một thể hiện sẽ được gọi tự động khi một thể hiện kết thúc “vòng đời” của nó thông qua bộ thu dọn rác tự động (Garbage  Collection). Destructor cũng có tên trùng với tên class. Để khai báo một destructor chúng ta đặt dấu “~” vào trước destructor
                
     Ví dụ



class Library
{
private int ibooktypes;
//Constructor
public Library()
{
ibooktypes = 7;
}
public Library(int value)
      {
            ibooktypes = value;
      }
            //Destructor

~ Library()
      {
            //thực thi câu lệnh khi hàm hủy hay phương thức hủy được gọi
      }
}
 ~Library() là destructor của lớp Library

2.   Instance constructor và Static constructor

Như bài học trước tôi đã giới thiệu, Các thành phần trong class có thể là instance và static. Constructors cũng là một thành phần của class, vậy Instance constructors và Static constructors có gì khác nhau? Chúng ta sẽ cùng tìm hiểu.

a.        Instance constructor

Một instance constructor( tạm dịch là một bộ khởi dựng thể hiện) sẽ khởi tạo một số giá trị khi một thể hiện của một lớp được tạo ra.
Ví dụ:

class Point
{
            public double x, y;
            public Point()
 {
                        this.x = 0;
                        this.y = 0;
            }
            public Point(double x, double y)
{
                        this.x = x;
                        this.y = y;
            }
            public static double Distance(Point a, Point b)
{
                        double xdiff = a.x – b.x;
                        double ydiff = a.y – b.y;
                        return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
            }
            public override string ToString()
{
                        return string.Format("({0}, {1})", x, y);
            }
}
class Test
{
            static void Main()
{
                        Point a = new Point();
                        Point b = new Point(3, 4);
                        double d = Point.Distance(a, b);
                        Console.WriteLine("Distance from {0} to {1} is {2}", a, b, d);
            }
      }
                                                      
Trong lớp Point có 2 instance constructors. Một không có đối số truyền vào và 2 constructor còn lại có 2 tham số kiểu double. Nếu class không có instance constructor nào thì constructor không có đối số sẽ được gọi tự động.

b.Static constructor

Nếu một lớp khai báo một phương thức khởi tạo tĩnh (static constructor), thì được đảm bảo rằng phương thức này sẽ được thực hiện trước bất cứ thể hiện nào của lớp được tạo ra. Static Constructor  hữu dụng khi chúng ta cần cài đặt một số công việc mà không thể thực hiện được thông qua chức năng khởi dựng và công việc cài đặt này chỉ được thực
duy nhất một lần. Static constructor không có thuộc tính truy cập, không có đối số và không được gọi tường minh mà sẽ được gọi tự động.

Ví dụ:

sing System;
using Personnel.Data;
class Employee
{
       private static DataSet ds;
       static Employee() {
                   ds = new DataSet(...);
       }
       public string Name;
       public decimal Salary;
       ...
}
Khi đó đối tượng ds sẽ được tạo ra khi trước khi ta tạo một thể hiện lớp emplyee.