[VB.NET] Phạm vi của biến

  • Thread starter thanhphong
  • Ngày gửi
T

thanhphong

Guest
1. Phạm vi của biến
1.1 Câu lệnh rẽ nhánh.

Đây là cấp bậc nhỏ nhất.
Mã:
Public Class Form1

    Dim x As Integer '←Bien nay co tac dung tren toan bo class. Level Class

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim y As Integer '←Bien nay chi co tac dung trong sub nay. level sub, function

        If x = y Then
            Dim z As Integer '←Bien nay chi co tac dung trong khoi block nay.
            z = x + y
        End If

    End Sub

End Class
Biến số được khai báo trong xxx~end xxx thì khi kết thúc end là biến này không còn tác dụng.
Ví dụ biến z được khai báo trong If ~ End If , thì khi ra khỏi End If , biến z không còn sử dụng được nữa.
(Còn nữa)
Đề nghị không comment cho tới khi có thông báo topic này đã xong.
Nguồn:
 
B

bvtvba

Guest
1.2 Trong các khối lệnh
Ngoài cấu trúc ○○ ~ End ○○ , còn có rất nhiều cấu trúc như For ~ Next chẳng hạn.
Sau đây tôi sẽ giới thiệu các khối lệnh tiêu biểu :
If ~ End IfNếu điều kiện logic thỏa mãn thì sẽ đi vào trong khối lệnh này. Ở bên trong có thể còn có rẽ nhánh Else, ElseIf
Try ~ End TryNếu có lỗi xảy ra thì đi vào trong này. Bên trong có thể còn có rẽ nhánh Catch,Finally
While ~ End WhileTrong khi điều kiện logic thỏa mãn thì...
Using ~ End UsingMô tả quy trình đảm bảo rằng tài nguyên được giải phóng.
SyncLock ~ End SyncLockMô tả một quá trình không thể được thực thi trong nhiều luồng.
With ~ End WithMô tả quá trình tham chiếu ngầm đến đối tượng.
Do ~ LoopVòng lặp
For ~ NextVòng lặp
Select ~ End SelectMô tả quá trình phân nhánh theo các điều kiện.
Các biến được khai báo trong các khối này có phạm vi khối chỉ có thể được sử dụng trong khối đó. Nếu bạn muốn sử dụng cùng một biến trên nhiều khối, bạn cần khai báo biến bên ngoài khối và nâng phạm vi của biến lên cao hơn một bậc.
Hãy xem ví dụ dưới đây :

Bạn cần đăng nhập để thấy hình ảnh

Trong code trên tôi có ba khối block.
Tôi khai báo biến userName ở khối đầu tiên.
Và khi chạy code trên lập tức sẽ báo lỗi, thông báo biến userName chưa được khai báo.
(còn nữa)
 

tuhocvba

Administrator
Thành viên BQT
Mã:
Dim userName as String
Với biến string, trong VB.NET nếu không khai báo giá trị khởi tạo ban đầu, VB.NET thường sẽ có cảnh báo. Nếu như có lỗi xảy ra, biến string này nhận giá trị là Null, khi đó các hàm xử lý chuỗi ký tự ở phía sau, chẳng hạn như hàm Len(s) có khả năng sẽ có lỗi.
Ngay khi khai báo biến, nếu ta gán giá trị khởi tạo cho biến, thì cảnh báo này sẽ biến mất.
Chẳng hạn:
Mã:
Dim s as string = ""
Hoặc:
Mã:
Dim s as string = Nothing
 
Ở đây tôi xin nêu một cách giải quyết khác :
Mã:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Try
        Dim userName As String
        userName = InputBox("Hãy nhập tên")

        If Len(userName) > 0 Then
            MsgBox("Xin chào bạn " & userName)
        End If
    Catch ex As Exception
        'Xử lý lỗi ở đây
        MsgBox("Có lỗi xảy ra" & ex.Message)
    End Try

End Sub
Xử lý với biến userName được đưa vào giữa Try~ Catch .
Đây là vị trí mà chương trình hoạt động bình thường. Phạm vi của biến này cũng được giới hạn ở bên trong khoảng nói trên mà thôi.
Nếu như bên trong khối lệnh Try~ Catch này lại có các khối lệnh con bên trong thì nó vẫn có hiệu lực.
Nhất là các khối lệnh With Me ~ End With thì lại càng vô hại.
Nhân tiện, trong C #, bạn có thể sử dụng {} để tạo các khối không có chức năng đặc biệt và bạn chỉ có thể sử dụng nó cho mục đích giới hạn phạm vi của các biến. VB không có khả năng tạo phạm vi như thế. Nếu bạn muốn các khối vô hại, With Me ~ End With là vô hại nhất (mặc dù không phải ở khắp mọi nơi). Ban đầu, With chỉ làm giảm sự cố khi nhập chương trình mà không có chức năng cụ thể nào. Trong ví dụ dưới đây, hai khối được tạo bằng With ~ End With, nhưng bản thân các khối không có ý nghĩa gì, chúng chỉ tách biệt phạm vi của các biến bên trong.
Mã:
With Me
    Dim count As Integer
    count = count + 111
    MsgBox(count) 'Ket qua : 111
End With

With Me
    Dim count As Integer 'Tao bien moi
    count = count + 222
    MsgBox(count) 'Ket qua: 222
End With
Tuy nhiên, tôi không khuyên bạn nên sử dụng nó theo cách này, vì With vô nghĩa có thể gây nhầm lẫn. Hãy coi đó là thông tin dành cho những người sử dụng nhiều {} trong các ngôn ngữ khác như C #.
 
1.3 Biến cấp độ thủ tục
Đây là các biến được khai báo trong Sub ~ End Sub、Function ~ End Function .
Chúng chỉ có tác dụng trong hàm hay thủ tục mà nó được khai báo.
Ta hãy xem xét ví dụ sau:
Mã:
Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim userName As String
        userName = InputBox("Hãy nhập tên")

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        'Lỗi xảy ra ở đây
        MsgBox("Xin chào " & userName)

    End Sub

End Class
Ở thủ tục Button2_Click, biến không được khai báo, chương trình sẽ không hiểu userName là gì, do đó sẽ xảy ra lỗi.
Do đó tôi khắc phục như sau :
Mã:
Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim userName As String
        userName = InputBox("Hãy nhập tên")

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        Dim userName As String
        MsgBox("Xin chào " & userName )

    End Sub

End Class
Chương trình bây giờ sẽ không lỗi nhưng sẽ không hiển thị tên mà người dùng nhập vào.
 
1.4 Biến cấp độ class
Class hiểu đơn giản là phạm vi trải dài từ Class ~ End Class .
Cách khai báo biến userName dưới đây sẽ giúp cho biến này có tác dụng trong mọi thủ tục nằm bên trong lớp mà nó được khai báo.
Mã:
Public Class Form1

    Dim userName As String

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        userName = InputBox("Hãy nhập tên")

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        MsgBox("Xin chào bạn " & userName)

    End Sub

End Class
Field-Trường:
Các biến được khai báo ở cấp độ lớp, chúng không còn là biến thông thường nữa, mà được coi là thành viên của lớp, và trở thành field (trường).
Nói cách khác, một biến có phạm vi cấp lớp đồng nghĩa với một trường.
Từ lớp khác có thể gọi được biến này thì bạn cần phải chỉ định từ khóa cho nó : Private, Protected, Friend, Public.
Tôi sẽ giải thích chi tiết sau. Nhưng khi chỉ định Private thì chắc chắn các lớp khác không thể truy cập tới biến này. Và khi chỉ định Public thì các lớp khác có thể truy cập vào biến này. Đối với Protected và Friend thì các lớp khác vẫn có thể truy cập tới nhưng sẽ có điều kiện.

Vì vậy khi khai báo biến cấp độ lớp, bạn nên chỉ định rõ ràng thay vì viết một cách mơ hồ.
Cách viết không khuyến khích: Dim userName As String
Cách viết khuyên dùng (chỉ định rõ ràng) : Private userName As String
Nói một cách chính xác, vì các biến cấp độ class là các trường (filed), là thành viên của Class chứ không phải là biến, có một số trường hợp áp dụng các quy tắc khác với các biến cục bộ (biến phạm vi thủ tục và biến phạm vi khối).
Ví dụ: bạn cần khai báo một biến ở trên nơi bạn đang sử dụng nó trong thủ tục của mình, nhưng bạn có thể khai báo các biến cấp lớp ở bất kỳ đâu. Bạn có thể khai báo nó ở đầu lớp hoặc ngay trước Lớp kết thúc.

Không thể suy luận kiểu biến: Trong ví dụ dưới đây, biến s2 là biến cục bộ, nhận giá trị là string, do đó nó được suy luận là kiểu biến string.
Tuy nhiên biến s1 nói chính xác là một trường thuộc class, cho nên nó không được suy luận kiểu biến.
Mã:
Public Class Form1

    Private s1 = "hihihaha"

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim s2 = "tuhocvba.net"

    End Sub

End Class
Nguồn:
Mã:
https://www.umayadia.com/VBStandard2/Standard09.htm
(Còn nữa)
 
2. Tuổi thọ của biến
Các biến được tạo ra khi chúng được khai báo trong phạm vi đó và biến mất khi chúng nằm ngoài phạm vi đó.
Chương trình sau đây dường như tính bằng cách thêm 1 mỗi khi nút bấm được nhấp, nhưng nó được hiển thị luôn là "1" mỗi khi nút được nhấp.
Mã:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim count As Integer
    count = count + 1

    MsgBox(count)

End Sub
Điều này là do số lượng biến được khai báo ở mức thủ tục này biến mất khi việc thực thi đến End Sub. Lần sau khi bạn nhấp vào nút, một biến đếm mới sẽ được tạo, nhưng đó là một biến mới, vì vậy giá trị của nó là 0.
Để giải quyết vấn đề này, chúng ta cần nâng phạm vi của các biến lên một bước cao hơn.
Mã:
Public Class Form1

    Private count As Integer

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        count = count + 1

        MsgBox(count)

    End Sub

End Class
Bây giờ số đếm là một trường cho lớp, nó sẽ tồn tại cho đến khi lớp biến mất (trong trường hợp của một biểu mẫu, cho đến khi biểu mẫu bị đóng).
Xin lưu ý rằng giải pháp này sẽ thay đổi phạm vi của chính biến. Nói cách khác, nó ban đầu chỉ được sử dụng trong thủ tục, nhưng sẽ rất phiền phức nếu nó biến mất, vì vậy nó được nâng cấp lên cấp độ lớp. Biến này sau đó sẽ được hiển thị cho các thủ tục khác.

Có một cách giải quyết khác.
Nếu bạn khai báo một biến cục bộ bằng cách sử dụng Static thay vì Dim như sau, biến sẽ không biến mất ngay cả khi nó vượt ra khỏi phạm vi và bạn có thể đếm như dự định.
Mã:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Static count As Integer
    count = count + 1

    MsgBox(count)

End Sub
Giải pháp này không làm thay đổi phạm vi của chính biến, vì vậy rất tốt khi nó không thể được truy cập bởi các thủ tục khác.
Các biến là biến cục bộ nhưng không biến mất khi kết thúc quá trình thực thi thủ tục là các hàm không tồn tại trong các ngôn ngữ lập trình chính khác như C #, Java và Python, và nhiều lập trình viên đang nhầm lẫn. Từ khóa static để sử dụng tính năng này cũng có nghĩa khác trong các ngôn ngữ khác và làm tăng thêm sự nhầm lẫn. Vì vậy, mặc dù tính năng này của VB rất hữu ích, nhưng người ta thường nói rằng bạn không nên sử dụng nó.
Chúng tôi khuyến cáo những người đang học VB cũng không nên sử dụng nó vì nó sẽ dẫn đến việc hiểu không đầy đủ về các quy tắc cơ bản khác. Nếu bạn đã hiểu rõ về VB và muốn sử dụng tính năng này một cách thuận tiện, thì xin cứ tiếp tục.
 
Top