2009-02-26 13 views
8

Tôi đã thấy điều này trong mã kế thừa và trong một số dự án mã nguồn mở .NET. Tôi không thể tưởng tượng một lý do để làm điều này. Chỉ cần sử dụng "null" có vẻ dễ dàng hơn nhiều với tôi.Tại sao những người sử dụng các giá trị ma thuật thay vì null trong mã của họ?

Ví dụ:

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != -1; 
     } 
    } 
} 

so

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != null; 
     } 
    } 
} 
+0

Bạn sẽ làm tốt hơn nhiều nếu bạn cho thấy một ví dụ ít nhất. – GEOCHET

+0

-1: không có mã. -1: không sao cả. Có chuyện gì vậy? Cái gì không hiệu quả? –

+0

Bạn đã đảo ngược séc (phải là parentID! = Null), nhưng tôi nghĩ câu hỏi là hợp lệ. +1 – erikkallen

Trả lời

0

Bạn đã thực sự nhìn vào ứng dụng để xem? Miễn là số ma thuật được giữ ở một nơi duy nhất với một tên mô tả nó có thể khá hữu ích.

+0

Có, chúng được giữ ở một nơi duy nhất với giá trị mô tả, như Null.NullInteger và Null.NullDate, nhưng tôi đã không thể tìm ra lý do tại sao nó hữu ích – Paco

+0

Sau đó, nó không phải là một "giá trị ma thuật" ở tất cả - giá trị ma thuật là các chữ trong mã nguồn không có ngữ cảnh và do đó có nghĩa là mơ hồ. –

+0

Tôi xem đây là một giá trị ma thuật bởi vì bạn phải biết nó không chỉ là một số nguyên hoặc ngày, nhưng bạn phải so sánh nó với Null.NullObject để biết ý nghĩa của nó. Bạn không thể biết rằng bạn phải so sánh nó với nullobject trước khi sử dụng giá trị. – Paco

3

Có một đối tượng rỗng có thể gây ra ngoại lệ được ném, trong khi mã lỗi (như trường hợp lỗi "-1") sẽ không ném ngoại lệ.

Điều này có thể quan trọng bằng các ngôn ngữ hoặc ứng dụng không xử lý tốt ngoại lệ.

2

Làm việc trên các kho dữ liệu lớn, đôi khi tôi sử dụng giá trị 0 thay vì nếu null, để chèn một giá trị không null vào khối lập phương của tôi. tôi luôn có 0 id tương ứng với giá trị 'Không xác định' trong tất cả các thứ nguyên, vì vậy tôi có một khối không có giá trị null.

sự quan tâm chính trong đó là phải có đơn giản hơn và hiệu quả hơn các truy vấn

4

Chúng thường được thói quen phát triển khi lập trình trong C. Nhiều một lập trình viên C sẽ được horified tại sự lãng phí ints nullable, mà ít nhất yêu cầu toàn bộ bit phụ, và thậm chí có thể là một con trỏ. Điều này đặc biệt xấu khi bạn biết giá trị sẽ dương và bạn có toàn bộ không gian của các giá trị âm để sử dụng cho cờ. -1 có nghĩa là không được thiết lập, -2 có thể có nghĩa là parentId thậm chí không có ý nghĩa trong ngữ cảnh của nút này, -3 có thể có nghĩa là nút có cha mẹ không thể xử lý công việc và để lại một phiên bản uống và không bao giờ được nhìn thấy một lần nữa, vv ...

Trong thế giới C# cleaness của int nullable (và dễ dàng tích hợp với RDMS) cùng với máy tính với 2GB + RAM có nghĩa là thói quen cũ C đang dần chết, nhưng thói quen cũ chết cứng.

1

Các loại giá trị không có sẵn không có sẵn ở mọi ngôn ngữ/môi trường; Chúng được thêm vào .Net 2.0. Nếu mã kế thừa của bạn là .Net dựa và được bắt đầu sử dụng khung công tác 1.1, thì câu trả lời của bạn là null không phải là một tùy chọn vào thời điểm đó.

11

Vì có giá trị "null", loại phải là giá trị rỗng. Đây hoạt động tốt với nhiều loại tài liệu tham khảo (bất kỳ lớp bạn xác định và các tiêu chuẩn thư viện), và nếu bạn nhìn bạn sẽ thấy rằng mọi người làm sử dụng vô bất cứ khi nào họ có một đối tượng tài liệu tham khảo không có giá trị

Employee employee = Employees.Find("John Smith"); 
if(employee == null) throw new Exception("Employee not found"); 

Vấn đề này xuất hiện khi bạn sử dụng các loại giá trị như int, char hoặc float. Không giống như các kiểu tham chiếu, trỏ đến một khối dữ liệu ở một nơi khác trong bộ nhớ, các giá trị này được lưu trữ và thao tác nội tuyến (không có con trỏ/tham chiếu).

Do điều này, theo mặc định, các loại giá trị không có giá trị rỗng. Trong mã bạn cung cấp, nó là không thể cho parentID là null (Tôi thực sự ngạc nhiên khi trình biên dịch của bạn có được - Visual Studio 2008 và có thể 2005 sẽ vẽ một gạch dưới màu xanh lá cây và cho bạn biết rằng câu lệnh luôn là false) .

Để cho một int để có một giá trị null, bạn cần phải khai báo nó như nullable

int? parentID; 

Bây giờ ParentID có thể chứa một giá trị null, bởi vì nó bây giờ là một con trỏ (tốt " tham chiếu ") đến số nguyên 32 bit, thay vì chỉ là số nguyên 32 bit.

Vì vậy, hy vọng bạn hiểu tại sao "giá trị ảo thuật" thường được sử dụng để đại diện cho vô với (kiểu giá trị) các loại cơ bản. Nó chỉ đơn giản là rất nhiều rắc rối, và thường là một hit hiệu suất lớn (tra cứu những gì boxing/unboxing là), để lưu trữ các loại giá trị như là một tham chiếu đến giá trị để cho phép chúng được null.

Edit: Để tham khảo thêm về boxing/unboxing (những gì bạn cần phải có một int == null), xem bài viết tại MSDN:

Boxing và Unboxing (C# Programming Guide)

Hiệu suất

Liên quan đến các bài tập đơn giản, quyền anh và unboxing là các quá trình tính toán tốn kém. Khi một loại giá trị được đóng hộp, một đối tượng mới phải được phân bổ và xây dựng. Ở mức độ thấp hơn, dàn diễn viên được yêu cầu cho unboxing cũng tốn kém tính toán. Để biết thêm thông tin, hãy xem Hiệu suất.

+0

Tôi không thể tưởng tượng một trường hợp đạt được hiệu suất rất nhỏ này là rất quan trọng. – Paco

+2

Chi phí là * không nhỏ * - bạn đang nói về việc thêm các hoạt động boxing/unboxing vào các loại dữ liệu và hoạt động * gây quỹ. Một điểm chuẩn thực hiện một phép toán số nguyên bổ sung có điều kiện chạy chậm hơn 9 lần khi các giá trị là vô giá trị vì phần trên đầu boxing. Hãy thử nó cho chính mình. – David

+0

Tôi biết phải mất bao lâu, nhưng tôi không tin vào việc tối ưu hóa các thuật toán O (N). – Paco

Các vấn đề liên quan