2008-08-08 32 views
77

Tại sao là Array.Length một int chứ không phải là uint. Điều này làm phiền tôi (chỉ một chút), bởi vì một giá trị độ dài không bao giờ có thể âm.Tại sao là Array.Length an int và không phải là uint

này cũng buộc tôi phải sử dụng một int cho một chiều dài-tài sản trên lớp của riêng tôi, bởi vì khi bạn định một int có giá trị, điều này cần phải được rõ ràng đúc ...

Vì vậy, câu hỏi cuối cùng là : có bất kỳ sử dụng cho một int không dấu (uint)? Ngay cả Microsoft dường như không sử dụng chúng.

+0

Mặc dù vấn đề được nêu bên dưới, tôi nghĩ rằng nó sẽ thay đổi thành UInt. – alan2here

+1

@ alan2đây thực hiện một thay đổi như vậy sẽ phá vỡ gần như tất cả các mã ra khỏi đó để nó sẽ không xảy ra nếu bạn hỏi tôi! – Peter

Trả lời

0

Thông thường, các giá trị số nguyên được ký, trừ khi bạn cần một giá trị chưa ký. Nó chỉ là cách chúng được sử dụng. Tôi có thể không đồng ý với sự lựa chọn đó, nhưng đó chỉ là cách thức của nó.

Hiện tại, với các hạn chế về bộ nhớ điển hình, nếu mảng hoặc cấu trúc dữ liệu tương tự của bạn cần chiều dài UInt32, bạn nên xem xét các cấu trúc dữ liệu khác.

Với một mảng byte, Int32 sẽ cung cấp cho bạn 2GB giá trị

+13

"nhưng đó chỉ là cách nó." - không, mọi thứ không bao giờ chỉ là cách họ đang có. Luôn luôn có một quyết định thiết kế được thực hiện, và nó luôn luôn trả tiền để hỏi tại sao. Người ta có thể học được điều gì đó từ những ưu và khuyết điểm, hoặc tham gia vào các nhà thiết kế (trong một số trường hợp) trong một cuộc thảo luận về họ. Luôn đặt câu hỏi! :) –

1

Tôi nghĩ rằng nó cũng có thể phải làm với việc đơn giản hóa mọi thứ ở mức thấp hơn, vì Array.Length dĩ nhiên sẽ được thêm vào một số âm tại một số điểm, nếu Array.Length không được gán, và thêm vào một int âm (hai bổ sung), có thể có kết quả lộn xộn.

+0

Vui lòng đưa ra một ví dụ? 'uint lenght = 3; int x = -4; Console.WriteLine (x + lenght);' yields -1 tốt. –

1

Có vẻ như không ai cung cấp câu trả lời cho "câu hỏi cuối cùng".

Tôi tin rằng việc sử dụng chính các int không dấu là cung cấp giao tiếp dễ dàng hơn với các hệ thống bên ngoài (P/Invoke và tương tự) và để đáp ứng nhu cầu của các ngôn ngữ khác nhau được chuyển sang .NET.

+0

Các loại chưa ký là cần thiết khi ghép nhiều giá trị nhỏ hơn để tạo ra một giá trị lớn hơn. Ta có thể kết hợp hai UInt16 để tạo một UInt32 bằng cách tính toán '(HighPart << 16) + LowPart', và ta có thể chia một UInt32 thành hai UInt16 thông qua' (Uint16) (Giá trị >> 16) 'và' (Uint16) (Giá trị & 65535) '. Các hoạt động như vậy sẽ rất bất tiện nếu 'LowPart' phải là một kiểu đã ký. Điều đó đã được nói, tương tác giữa các loại đã ký và chưa ký thường gây nhầm lẫn và có vấn đề. Các loại chưa được ký nên theo nhiều cách được coi là một thế giới của riêng chúng. – supercat

45

Nhiều lý do:

  • uint là không CLS phù hợp, do đó làm một xây dựng trong loại (mảng) phụ thuộc vào nó đã có vấn đề
  • Bộ thực thi như thiết kế ban đầu cấm bất kỳ đối tượng trên heap chiếm hơn 2GB bộ nhớ. Vì mảng có kích thước tối đa nhỏ hơn hoặc bằng giới hạn này sẽ là byte mới [int.MaxValue], nó sẽ khiến mọi người khó hiểu để có thể tạo ra độ dài mảng tích cực nhưng không hợp lệ.
  • Trong lịch sử C# thừa hưởng nhiều cú pháp và quy ước của nó từ C và C++.Trong các mảng này chỉ đơn giản là số học con trỏ để việc lập chỉ mục mảng tiêu cực là có thể (mặc dù thông thường là bất hợp pháp và nguy hiểm). Vì nhiều mã hiện có giả định rằng chỉ mục mảng được ký này sẽ là một yếu tố
  • Trên một lưu ý liên quan, việc sử dụng các số nguyên đã ký cho chỉ mục mảng trong C/C++ có nghĩa là interop với các ngôn ngữ này và chức năng không được quản lý sẽ yêu cầu sử dụng ints trong những trường hợp anyway, có thể gây nhầm lẫn do sự mâu thuẫn.
  • Việc triển khai BinarySearch (thành phần rất hữu ích của nhiều thuật toán) dựa vào việc có thể sử dụng dải âm của int để cho biết giá trị không được tìm thấy vị trí mà tại đó giá trị như vậy sẽ được chèn vào để duy trì sắp xếp.
  • Khi hoạt động trên một mảng, có khả năng bạn sẽ muốn lấy chênh lệch âm của chỉ mục hiện tại. Nếu bạn sử dụng một bù đắp mà sẽ đưa bạn qua sự bắt đầu của mảng bằng cách sử dụng đơn vị sau đó quấn quanh hành vi sẽ làm cho chỉ mục của bạn có thể hợp pháp (trong đó nó là tích cực). Với kết quả int sẽ là bất hợp pháp (nhưng an toàn vì thời gian chạy sẽ bảo vệ chống lại việc đọc bộ nhớ không hợp lệ)
+2

Nếu không có gì trên heap có thể trên 2Gb, thì hầu như tất cả các mảng có độ dài int.MaxValue là bất hợp pháp vì hầu hết các loại đều lớn hơn 1 byte. – ScottS

+0

thực sự nhưng ((uint) (int.MaxValue)) + 1 sẽ được đảm bảo sai cho * mọi thứ *. int là chính nó xa hoàn hảo, nhưng sự cân bằng của sự vật làm cho nó hợp pháp để ở với int như loại. – ShuggyCoUk

+0

Bắt đầu với kiểu khai phá ArrayIndex (về cơ bản size_t) sẽ dịch một cách sạch sẽ và an toàn thành một int khi cần thiết có thể sẽ làm cho nó dễ dàng hơn trong tương lai để thực sự sử dụng cho phép> 2GB mảng trong tương lai với ít đau hơn. Nhưng thực dụng nói java có vấn đề tương tự vậy tại sao lại mạo hiểm – ShuggyCoUk

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