2011-02-05 36 views
5

Có thể một số người vui lòng giải thích, Điều gì xảy ra khi loại tham chiếu được xác định bên trong loại giá trị. tôi viết đoạn mã sau:Cấu trúc bên trong lớp học

namespace ClassInsideStruct 
{ 
    class ClassInsideStruct 
    { 
     static void Main(string[] args) 
     { 

      ValueType ObjVal = new ValueType(10); 
      ObjVal.Display(); 

      ValueType.ReferenceType ObjValRef = new ValueType.ReferenceType(10); 
      ObjValRef.Display(); 

      Test(ObjVal, ObjValRef); 

      ObjVal.Display(); 
      ObjValRef.Display(); 

      Console.ReadKey(); 

     } 

     private static void Test(ValueType v, ValueType.ReferenceType r) 
     { 
      v.SValue = 50; 
      r.RValue = 50; 
     } 

    } 

    struct ValueType 
    { 

     int StructNum; 
     ReferenceType ObjRef; 

     public ValueType(int i) 
     { 
      StructNum = i; 
      ObjRef = new ReferenceType(i); 
     } 

     public int SValue 
     { 
      get { return StructNum; } 
      set 
      { 
       StructNum = value; 
       ObjRef.RValue = value; 
      } 
     } 

     public void Display() 
     { 
      Console.WriteLine("ValueType: " + StructNum); 
      Console.Write("ReferenceType Inside ValueType Instance: "); 
      ObjRef.Display(); 
     } 

     public class ReferenceType 
     { 

      int ClassNum; 

      public ReferenceType(int i) 
      { 
       ClassNum = i; 
      } 

      public void Display() 
      { 
       Console.WriteLine("Reference Type: " + ClassNum); 
      } 

      public int RValue 
      { 
       get { return ClassNum; } 
       set { ClassNum = value; } 
      } 

     } 

    } 

} 

Những kết quả đầu ra:

 
ValueType: 10 
ReferenceType Inside ValueType Instance: Reference Type: 10 
Reference Type: 10 
ValueType: 10 
ReferenceType Inside ValueType Instance: Reference Type: 50 
Reference Type: 50 

Tôi tò mò muốn biết, sau khi gọi phương thức Test(ObjVal, ObjValRef), làm thế nào các giá trị của ReferenceType được thay đổi thành 50 mà nằm bên trong ValueType có giá trị nào không thay đổi?

+1

Vị trí của lớp đối với cấu trúc không liên quan. Nó chỉ là một kiểu lồng nhau (và trong C# - không giống như nói Java hoặc Scala - nó là * không * phụ thuộc vào kiểu kèm theo). Đó là cùng ngữ nghĩa như thể 'ReferenceType' là * không * lồng nhau. Đừng nhầm lẫn giữa các loại và các biến với một kiểu nhất định và các đối tượng được tạo ra của một kiểu đã cho. –

Trả lời

2

Tôi không biết chắc chắn, nhưng trình biên dịch có thể tách mã thành một lớp riêng biệt và sau đó chỉ thực thi các quy tắc bắt buộc. Khi bạn sử dụng một loại giá trị, giá trị được sao chép mỗi khi nó được chuyển vào một phương thức. Tham chiếu đến một loại tham chiếu sẽ được sao chép, nhưng nó tham chiếu đến cùng một đối tượng. Cùng một đối tượng tham chiếu này sẽ được thay đổi trong khi loại giá trị được sao chép sẽ bị thay đổi. Bản gốc bạn đã chuyển sẽ không phản ánh các thay đổi trên bản sao.

+0

+1 Tôi thích cách "sao chép" được đề cập một cách rõ ràng. Yêu cầu này duy trì ngữ nghĩa gọi kiểu cấu trúc độc lập khi thực hiện thực tế. –

1

Giá trị bên trong loại giá trị là tham chiếu, rằng nó không bị thay đổi. Nhưng giá trị được chỉ bởi tham chiếu có thể dễ dàng thay đổi.

2

Vì loại tham chiếu là loại tham chiếu và loại giá trị là loại giá trị. Không có vấn đề nơi họ cư trú.

Và cũng loại Giá trị không thay đổi, không phải thay đổi Tham chiếu mà nó đang nắm giữ. Loại tham chiếu được thay đổi (Đọc kỹ từ của tôi).

tức là dữ liệu cơ bản tại địa chỉ đó bị thay đổi. Tham chiếu được tổ chức theo loại giá trị vẫn giữ nguyên.

+0

Tôi thích sự bắt đầu của điều này. Có lẽ làm rõ để giải thích 'đối tượng t = Guid.New; f (t) ' –

+0

@pst không phải là Mới là Guid.NewGuid. Và nó trả về một kiểu giá trị Guid struct sau đó nó được đóng hộp vào đối tượng và tham chiếu được trao cho t ... BTW f() làm là gì ... –

1

Các loại tham chiếu được chuyển vào các phương thức dưới dạng con trỏ, vì vậy việc sửa đổi nội dung sẽ sửa đổi cùng một vị trí trong bộ nhớ. Các kiểu giá trị được chuyển vào các phương thức bằng cách gửi giá trị trên ngăn xếp cuộc gọi.

+1

Và một con trỏ được gửi ... dum dum dum ... as giá trị trên ngăn xếp! Câu trả lời này không đúng, nhưng điều quan trọng là nhận ra "sự khác biệt" lớn là ngữ nghĩa sao cho * không có bản sao/trùng lặp * của một đối tượng kiểu tham chiếu được thực hiện khi nó được truyền (điều này bao gồm * loại bỏ * giá trị kiểu). Các đối tượng có giá trị * có thể * cũng được chuyển qua "tham chiếu" nếu nó sao cho bản sao/bản sao được tạo ra để bảo toàn ngữ nghĩa; việc triển khai chỉ là triển khai. –

-1

khi lập trình, điều quan trọng là phải hiểu rằng gọi phương thức lấy đối số ngụ ý/bao gồm/giống như gán giá trị cho các đối số. cộng:

static void Main(string[] args) 
{ 

    ValueType ObjVal = new ValueType(10); 
    ObjVal.Display(); 

    ValueType.ReferenceType ObjValRef = new ValueType.ReferenceType(10); 
    ObjValRef.Display(); 

    //call to Test(ObjVal, ObjValRef); replaced by the following 4 lines 
    ValueType v = ObjVal; 
    ReferenceType r = ObjValRef; 
    v.SValue = 50; 
    r.RValue = 50; 

    ObjVal.Display(); 
    ObjValRef.Display(); 

    Console.ReadKey(); 

} 

nên cho kết quả tương tự như ví dụ của bạn ở trên. khi bạn khai báo ValueType v = ObjVal; bạn đang tạo một bản sao của đối tượng struct thực tế, có nghĩa là v là một đối tượng riêng biệt tất cả cùng nhau. vì vậy việc thay đổi giá trị của các thành viên của nó sẽ không ảnh hưởng đến ObjVal.

tuy nhiên, Loại tham chiếu r = ObjValRef; tạo bản sao của tham chiếu. Vì vậy, bây giờ có hai tham chiếu, ObjValRefr, trỏ đến cùng một đối tượng. Cụ thể là đối tượng được tạo khi gọi new ValueType.ReferenceType (10);

vì vậy khi thay đổi thành viên của đối tượng trỏ đến bởi bất kỳ tham chiếu nào trong số hai, đối tượng này thay đổi, bất kể con trỏ nào được sử dụng để thực hiện thay đổi.

oh, by the ..một tham chiếu chỉ là một địa chỉ của một đối tượng. thường thì đây là số 32 bit, nhưng điều này thay đổi từ ngôn ngữ này sang ngôn ngữ khác và từ bộ vi xử lý sang bộ xử lý.

và tự thay đổi bản sao tham chiếu, ví dụ: r = null; sẽ không ảnh hưởng đến tham chiếu "gốc" ObjValRef, vì r là bản sao của ObjValRef và không phải là ObjValRef. nó chỉ xuất hiện như thể chúng giống nhau, vì cả hai đều trỏ đến cùng một đối tượng.

bạn có thể nghĩ đối tượng thực là địa điểm (công viên hoặc một số tòa nhà nổi tiếng, có thể là "công viên núi trắng") và tham chiếu làm biển báo chỉ đường đến địa điểm này. có thể có nhiều dấu hiệu đường phố chỉ vào cùng một vị trí, nhưng điều này không có nghĩa là có nhiều "công viên núi trắng". và đây là sự khác biệt giữa các loại giá trị và loại tham chiếu.

+0

Tôi hiểu, tại sao giá trị của 'r' bị thay đổi. Tôi muốn biết tại sao 'RValue' của 'v' đã bị thay đổi. Tuy nhiên, cảm ơn bạn đã làm rõ loại giá trị và loại tham chiếu. – NaveenBhat

+0

tốt, thực sự nó đã không. RValue vẫn có cùng giá trị, đó là địa chỉ của một đối tượng. đối tượng này lần lượt đã thay đổi nội bộ (thành viên ClassNum của nó đã được đặt thành 50). và thực sự chính xác, có hai RValue liên quan. một bên trong đối tượng struct được gọi là ObjVal và một đối tượng bên trong đối tượng struct được gọi là v. v chỉ tồn tại bên trong phương thức Test. khi v được tạo ra, tất cả các dữ liệu từ ObjVal được sao chép vào v, và điều này bao gồm RValue, mà thực sự là một số nguyên 32 bit, trỏ đến địa chỉ của một đối tượng kiểu ValueType.ReferenceType. – davogotland

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