2010-09-01 36 views
37

Tôi đang làm việc với một số mã số VB.NET dường như đang truyền một giá trị boolean cho một số nguyên sử dụng CInt(myBoolean). Điều kỳ lạ đang xảy ra là nó trả về -1 nếu giá trị là đúng. Ví dụ:Đưa một boolean vào một số nguyên trả về -1 cho đúng?

CInt(True) // returns -1 
CInt(False) // returns 0 

Điều này có phổ biến ở các ngôn ngữ khác không?

Tôi nghĩ rằng boolean sẽ là 1 nếu đúng và 0 nếu sai. Ngoài ra, có cách nào để làm cho Visual Basic gán 1 cho đúng thay vì gán -1?

Trả lời

35

Thông thường, giá trị sai được biểu thị bằng 0 và giá trị true được biểu thị bằng bất kỳ giá trị số nguyên không 0 nào. Giá trị cụ thể cho đúng và sai (trong số những thứ khác) là những thứ mà bạn không nên dựa vào - chúng có thể có khả năng được triển khai cụ thể. Tôi không chắc chắn những gì bạn đang cố gắng làm, nhưng nó có lẽ sẽ là tốt nhất để không dựa vào True hoặc False có bất kỳ giá trị số nguyên cụ thể trừ khi bạn hoàn toàn phải.

Lời giải thích tốt nhất mà tôi có thể tìm cho hành vi cụ thể của VB đến từ Wikipedia:

Boolean liên tục Đúng có giá trị số -1. Điều này là do kiểu dữ liệu Boolean được lưu trữ dưới dạng số nguyên được ký 16 bit. Trong cấu trúc này −1 đánh giá đến 16 nhị phân 1s (giá trị Boolean True) và 0 là 16 0 (giá trị Boolean False). Điều này là rõ ràng khi thực hiện một hoạt động không trên một giá trị số nguyên 16 bit đã ký 0 sẽ trả về giá trị số nguyên −1, nói cách khác là True = Not False. Chức năng cố hữu này trở nên đặc biệt hữu ích khi thực hiện các phép toán logic trên các bit riêng lẻ của một số nguyên như And, Or, Xor và Not. [4] Định nghĩa này của True cũng phù hợp với BASIC kể từ đầu những năm 1970 Microsoft BASIC thực hiện và cũng liên quan đến các đặc điểm của hướng dẫn CPU tại thời điểm đó.

+2

Tôi vừa thử nghiệm mẫu này. Một boolean trong VB.NET không bằng '-1', nó chỉ bằng' 1'. Tôi đã kiểm tra điều này bằng cách tạo một cấu trúc với hai trường chồng chéo bằng cách sử dụng FieldOffsetAttribute. Bằng cách đó bạn có thể thấy giá trị nhị phân chính xác của boolean.'CInt' chỉ là một chuyển đổi. Đề cập đến tài liệu cũ không thực sự giúp tôi đoán. –

+1

Tôi đã chuyển 'True'into một hàm đã chấp nhận một số nguyên và nhận giá trị' -1' trong VB.NET. Trong bài viết Martjin references (http://msdn.microsoft.com/en-us/library/ae382yt8.aspx) có vẻ như cách bạn chuyển đổi Boolean xác định giá trị số nguyên nào bạn nhận được. –

9

Dường như là hình ảnh xác thực và tôi không biết bất kỳ ví dụ nào khác về hành vi này.

http://msdn.microsoft.com/en-us/library/ae382yt8.aspx chỉ định hành vi này, với nhận xét sorta "Don't do that, mkay" with it. Do lưu ý tiếp tục xuống:

chuyển đổi trong khung

Phương pháp ToInt32 của lớp Chuyển đổi trong namespace System chuyển Đúng như 1.

Nếu bạn phải chuyển đổi giá trị Boolean thành kiểu dữ liệu số, hãy cẩn thận về phương pháp chuyển đổi bạn sử dụng.

11

Một tác phẩm xung quanh để sử dụng ban đầu của bạn sẽ là:

Dim i As Integer = CInt(Int(False)) 

này sẽ trả về một 0.

Dim i As Integer = CInt(Int(True)) 

này sẽ trả về một 1.

4

Các MSDN documentation cung cấp một số cái nhìn sâu sắc có giá trị :

B giá trị oolean không được lưu trữ dưới dạng số, và các giá trị được lưu trữ không có ý định tương đương với số. Bạn không bao giờ nên viết mã dựa trên các giá trị số tương đương cho True và False.Bất cứ khi nào có thể, bạn nên hạn chế việc sử dụng các biến Boolean cho các giá trị logic mà chúng được thiết kế.

4

tôi đã cùng một vấn đề và sử dụng Math.Abs chức năng trên kết quả :)

4

Nhiều phiên bản của BASIC trong những năm 1970 và năm 1980 thực hiện số học chút khôn ngoan với họ ANDOR nhà khai thác, và làm cho biểu thức điều kiện đúng đánh giá thành -1 (là giá trị "tất cả các bit-set"). Tôi không chắc chắn lý do tại sao quyết định đã được thực hiện để có biểu thức điều kiện thực sự đánh giá đến một giá trị tất cả các bit-set; có thể sử dụng AND để che dấu một số nguyên so với biểu thức có điều kiện có thể nhanh hơn nhân, nhưng do đó cơ chế bên trong của trình thông dịch sự khác biệt sẽ có chút ít.

Trong mọi trường hợp, các phiên bản BASIC đầu tiên do Microsoft sản xuất cho PC tuân theo truyền thống có điều kiện thực sự được đánh giá là -1 (tất cả các bit-bộ); kể từ khi QuickBASIC lần lượt được cho là tương thích với những người đó, và Visual Basic được cho là tương thích với QuickBASIC, họ đã sử dụng cùng một biểu diễn. Mặc dù. Net nhận ra các số nguyên và Booleans như các kiểu khác nhau, vb.net muốn cung cấp một đường dẫn di trú cho các chương trình VB6 có thể dựa vào hành vi cũ. Với "Option Strict Off", VB.Net sẽ ngầm chuyển đổi một giá trị Boolean của True thành một số nguyên -1; trong khi hầu hết các lập trình viên sử dụng Option Strict On, thì sẽ khó hiểu khi có hành vi của CInt() khác với hành vi chuyển đổi tiềm ẩn.

3

Tôi đã thử nghiệm nó và nhận được kết quả như sau:

Public Module BooleanTest 
Public Function GetTrue() As Boolean 
    GetTrue = True 
End Function 
End Module 

...

[StructLayout(LayoutKind.Explicit)] 
struct MyStruct 
{ 
    [FieldOffset(0)] 
    public bool MyBool; 
    [FieldOffset(0)] 
    public int MyInt32; 
} 

static void Main(string[] args) 
{ 
    MyStruct b1, b2; 
    b1.MyInt32 = 0; 
    b2.MyInt32 = 0; 
    b1.MyBool = BooleanTest.BooleanTest.GetTrue(); 
    b2.MyBool = true; 
    Console.WriteLine(b1.MyInt32); 
    Console.WriteLine(b2.MyInt32); 
} 

này sẽ cho kết quả:

Tôi hy vọng điều này chứng minh rằng tất cả các giá trị True bên trong .NET luôn giống nhau. Lý do rất đơn giản: Tất cả các thành viên .NET phải liên lạc với nhau. Nó sẽ là lạ nếu object.Equals(trueFromCSharp, trueFromVB) sẽ dẫn đến sai (như sẽ trueFromCSharp == trueFromVB).

CInt chỉ là một chức năng sẽ chuyển đổi True thành -1. Một chức năng khác Int sẽ trả lại 1. Nhưng đây là những người chuyển đổi và không nói bất cứ điều gì về các giá trị nhị phân.

1

Tôi đã gặp vấn đề tương tự với MySQL vì điều này không có loại Boolean chỉ là một tinyint (1).

giải pháp của tôi là viết một hàm chuyển đổi để đảm bảo rằng các giá trị là chính xác trước khi chèn chúng vào cơ sở dữ liệu

 Public Function BoolToMySql(bVal As Boolean) As Integer 
      Dim retVal As Integer 
      If bVal = True Then 
       retVal = 1 
      Else 
       retVal = 0 
      End If 
       BoolToMySql = retVal 
     End Function 
1

Tôi hy vọng đó là có thể giúp đỡ người khác làm việc với Booleans bên trong VB.NET. Cũng giống như một cách tốt hơn để viết VB.NET mà Roger đã viết:

Public Function BoolToMySql(bVal As Boolean) As Integer 
    return If(bVal, 1, 0) 
End Function 
Các vấn đề liên quan