2012-01-11 31 views
7

Sự khác biệt giữa các loại tham chiếu và loại giá trị thường gây nhầm lẫn cho người mới bắt đầu do không hiểu biến số của loại giá trị thực sự nắm giữ. Chúng ta biết rằng:Loại tham chiếu - chúng tôi có thể xem tham chiếu thực tế không?

  • Giá trị các loại lưu trữ các thực tế giá trị
  • loại Reference chỉ lưu trữ các tham khảo đến đối tượng

Có thể kiểm tra từng loại biến hoặc là thấy giá trị hoặc tham chiếu thực tế chính nó? Tài liệu tham khảo có được lưu trữ như một loại giá trị được mã hóa không? Tôi biết rằng tài liệu tham khảo có thể được thông qua bởi giá trị vì vậy tôi giả định như vậy.

Tôi nghĩ điều này sẽ giúp người mới đến với sự hiểu biết của họ và rất thú vị để khám phá.

+1

Điều duy nhất bạn sẽ thấy là địa chỉ, một số dường như ngẫu nhiên. Tại sao bạn muốn thấy điều này? – Dykam

+3

Để xi măng ý tưởng rằng trong biến không phải là đối tượng mà họ đặt, mà là một địa chỉ. Làm thế nào chúng ta sẽ truy cập này? –

+1

http://stackoverflow.com/questions/1978232/how-can-i-display-the-actual-value-of-a-reference-in-c-sharp –

Trả lời

10

Có thể kiểm tra từng loại biến để xem giá trị hoặc tham chiếu thực tế không?

Chỉ cần làm rõ, các giá trị của một biến tham khảo loại một tham chiếu. Tham chiếu là giá trị.

Tham chiếu là một loại giá trị, giống như một int là một loại giá trị. Không giống như int, tham chiếu là giá trị chỉ có thể là được sao chépbị hủy đăng ký; bạn không thể quan sát giá trị của nó trực tiếp trong C#, bởi vì giá trị của nó là một chi tiết thực hiện của bộ thu gom rác.

Tham chiếu có được lưu trữ như một loại giá trị được mã hóa không?

Có, chính xác. Trong thực tế, một tham chiếu là một số nguyên 32 hoặc 64 bit (tùy thuộc vào việc bạn đang trong quá trình 32 hay 64 bit) đó là một con trỏ tới một cấu trúc nào đó được biết đến với bộ gom rác như được liên kết với dữ liệu của đối tượng được gọi đến .

Nếu bạn muốn xem trực tiếp tài liệu tham khảo, công cụ để làm như vậy là trình gỡ lỗi. Tải mã C# của bạn vào trình gỡ lỗi, biên dịch nó, chạy nó, nhấn một điểm ngắt và xem trạng thái của ngăn xếp và thanh ghi. Với một chút thông minh, bạn sẽ có thể tìm ra vị trí ngăn xếp và sổ đăng ký tương ứng với biến cục bộ nào. Các vị trí tương ứng với biến cục bộ của loại giá trị sẽ chứa các giá trị; các loại tham chiếu sẽ chứa các giá trị giống như con trỏ. Nếu bạn kiểm tra các con trỏ đó trong cửa sổ bộ nhớ, thì bạn sẽ xem xét các cấu trúc được duy trì bởi bộ thu gom rác mô tả nội dung của đối tượng.

+3

Tôi nghĩ rằng điều quan trọng cần lưu ý là khi triển khai .net hiện có có thể lưu trữ địa chỉ (của bản ghi đối tượng-thông tin) trong biến tham chiếu, không có gì đảm bảo rằng các phiên bản sau sẽ làm như vậy. Nó sẽ có thể, ví dụ, rằng một số bit của một biến tham chiếu sẽ là một chỉ số lựa chọn một trong một số đống, trong khi các bit khác là một chỉ mục trong heap đó. Trong khi một hệ thống như vậy có thể không hiệu quả với các bộ vi xử lý hiện có, việc thiết kế các bộ vi xử lý trong tương lai xung quanh mô hình như vậy có thể cho phép sử dụng bộ nhớ cache hiệu quả hơn. Mã .net hiện tại không nên quan tâm đến các chi tiết đó. – supercat

+0

@supercat: Tuyệt đối. Trong thực tế tài liệu tham khảo có thể được thực hiện như xử lý hoàn toàn mờ đục mà chỉ có ý nghĩa trong khi họ chỉ số vào một số bảng thuộc sở hữu của các nhà sưu tập rác; không có lý do tại sao * bất kỳ * bit trong một tham chiếu cần phải có một ý nghĩa cụ thể. Khi nó xảy ra, trong việc triển khai ngày nay, mỗi bit tham chiếu * là * có ý nghĩa vì nó có thể được hiểu là một con trỏ. Nhưng điều đó có thể thay đổi bất cứ lúc nào. –

+0

Ngoài sự tò mò, trong khi CPU hiện tại có lẽ sẽ không cho phép những thứ như vậy rất hiệu quả, tôi tự hỏi liệu nó có đáng giá trong các CPU tương lai để có một đống đối tượng nhỏ cho các đối tượng có dữ liệu là 8 (có thể là 16) byte hay ít hơn , trong đó mỗi khe trong bảng đối tượng sẽ giữ dữ liệu đối tượng thực tế thay vì một con trỏ đến nó. Trên các CPU hiện có, người ta sẽ cần thêm hướng dẫn cho mỗi truy cập heap để xác định vùng nào có tham chiếu đã cho, nhưng nếu có lệnh "get address address" được sử dụng một chút trong tham chiếu để chọn indirection đơn hoặc kép ... – supercat

1

Bạn có thể thực hiện việc này với đối tượng được ghim khá dễ dàng;

GCHandle gch=GCHandle.Alloc(data, GCHandleType.Pinned); 
IntPtr AddressInMemory=gch.AddrOfPinnedObject(); 
+0

Thao tác này sẽ không hoạt động đối với [loại không thể ghi được] (http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx), giống như hầu như tất cả các lớp. – svick

+0

Tôi đã chỉnh sửa. Có vẻ như lần duy nhất tôi cần điều này là với các nguyên thủy. –

1

Bạn có thể làm điều đó với unsafe mã:

unsafe 
    static void Main(string[] args) 
    { 
     string s = "Hello"; 

     fixed (char* pc = s) 
     {     
      IntPtr p = (IntPtr)pc; 
      Console.WriteLine(p); // here is your meaningless address 
     }    
    } 
+0

Điều này tạo ra một bản sao của s, vì vậy bạn tại sao không pin s trực tiếp? –

+0

Chúng tôi sẽ không sử dụng 's' cho bất cứ điều gì. –

+0

@EugenRieck Bạn có nguồn cho tuyên bố đó không? Tôi không thấy sao chép ở đây. – CodesInChaos

5

Đây có lẽ là một cho Jon Skeet, nhưng tôi có thể có một góc độ khác nhau về nó:

Đừng lo lắng quá nhiều về cách những thứ này được thể hiện trong bộ nhớ. Trừ khi bạn đã đọc qua toàn bộ đặc tả ngôn ngữ - ai làm điều đó? - bạn thực sự không cần phải biết. Có thật không. Đừng bận tâm ghi nhớ những gì dữ liệu được lưu trữ ở đâu - rất có thể, rằng đây là thực hiện cụ thể.

Thay vào đó, hãy suy nghĩ về mặt ngữ nghĩa, ví dụ: rằng loại giá trị được chuyển đến hàm được sao chép, trong khi loại tham chiếu là được tham chiếu. Những thứ như thế.

Bạn thực sự không muốn biết tuyên bố của loại thực sự nắm giữ là gì. Tin tôi đi. Những gì bạn muốn biết, là cách hoạt động của nó.

+2

+1 Đây là nơi Eric Lippert [nói] (http://blogs.msdn.com/b/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx) điều tương tự.Địa chỉ là chi tiết triển khai, đặc tả ngôn ngữ không đề cập đến địa chỉ khi chỉ định tham chiếu. Tìm hiểu cách chúng hoạt động và không phải cách chúng hoạt động. – MarkJ

+2

Trong khi tôi đồng ý với tuyên bố của bạn, tôi không cảm thấy nó hoàn toàn phù hợp với câu hỏi. Tôi nghĩ anh ấy muốn biết làm thế nào để làm điều đó - không phải ý kiến ​​của bạn về lý do tại sao nó không quan trọng. Dựa vào cách hoạt động của các chức năng phức tạp có thể làm cho bạn trở thành một kỹ sư tốt hơn ngay cả khi bạn không tìm thấy sử dụng ngay lập tức cho kiến ​​thức đó. –

+0

Trong khi tôi vừa cảm ơn và đồng ý với câu trả lời của bạn, nó không giải quyết được vấn đề của tôi. Tôi chỉ muốn truy cập vào địa chỉ ** chỉ để chứng minh là có ** không có lý do nào khác. Tôi đồng ý với @ AdamG.Carstensen. –

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