2010-09-04 43 views
5

Bằng cách giải thích, hãy loại giá trị này trong C#:Có thể tạo chu trình tham chiếu chỉ sử dụng các loại giá trị không?

struct ObjRef 
{ 
    public object Value; 
    public ObjRef(object value) { Value = value; } 
} 

tôi có thể tưởng tượng một đồ thị đối tượng nơi có hai đóng hộp trường thuộc loại này, từng nắm giữ một tham chiếu đến người kia. Đây là những gì tôi có ý nghĩa bởi một chu trình tham chiếu chỉ với các kiểu giá trị.

Câu hỏi của tôi là liệu biểu đồ đối tượng đó có thể được xây dựng trong .NET hay không. Về mặt khái niệm, việc xây dựng, nếu nó tồn tại, sẽ như sau:

object left = new ObjRef(); 
object right = new ObjRef(left); 
left.Value = right; 

nhưng rõ ràng, dòng cuối cùng không có giá trị C#. Đặt dòng cuối cùng:

((ObjRef)left).Value = right; 

không đạt được kết quả như hộp bỏ unbox left và bạn sẽ tắt một bản sao. Vì vậy, ít nhất trong C# thẳng, nó không giống như xây dựng là có thể.

Có ai biết liệu xây dựng có thể đạt được bằng cách sử dụng phản chiếu, mã không an toàn, dynamic, mã IL hoặc theo bất kỳ cách nào khác không? Hoặc, bất cứ ai có thể cho thấy rằng CLR có hiệu quả ngăn chặn một chu kỳ tham chiếu?

Xin lưu ý rằng tôi không thực sự muốn tạo biểu đồ đối tượng như vậy. Thay vào đó, câu trả lời có thể ảnh hưởng đến việc thiết kế các thuật toán làm việc với các đồ thị đối tượng, chẳng hạn như các trình định dạng tuần tự hóa/deserialization.


EDIT

Như Brian đề nghị, nó thực sự có thể thay đổi giá trị đóng hộp mà không unboxing nó, bằng cách đúc nó vào một loại giao diện thay vì kiểu giá trị. Vì vậy, cho mã này:

interface IObjRef 
{ 
    IObjRef Value { get; set; } 
} 

struct ObjRef : IObjRef 
{ 
    IObjRef value; 
    public IObjRef Value { get { return value; } set { this.value = value; } } 
    public ObjRef(IObjRef value) { this.value = value; } 
} 

sau đó tham chiếu vòng tôi mô tả có thể được xây dựng như thế này:

IObjRef left = new ObjRef(); 
IObjRef right = new ObjRef(left); 
left.Value = right; 

Mà về cơ bản lá chúng tôi với lý do # 72 lý do tại sao có thể thay đổi giá trị loại là ác.

Trả lời

2

Điều này có thể bằng cách sử dụng giao diện và có loại giá trị triển khai giao diện và tham chiếu với nhau. Điều này cho phép họ tạo chu trình thông qua các giá trị được đóng hộp vì cấu trúc khi được sử dụng với tham chiếu giao tiếp sẽ được đóng hộp.

mẫu nhanh

interface ICycle 
{ 
    void SetOther(ICycle other); 
} 

struct Cycle : ICycle 
{ 
    ICycle value; 
    public void SetOther(ICycle other) 
    { 
     value = other; 
    } 
} 

class Example 
{ 
    static void CreateCycle() 
    { 
     ICycle left = new Cycle(); // Left is now boxed 
     ICycle right = new Cycle(); // Right is now boxed 
     left.SetOther(right); 
     right.SetOther(left); // Cycle 
    } 
} 

Tôi chia sẻ câu hỏi của Brian mặc dù về tự hỏi điều gì lợi thế này sẽ cung cấp cho bạn.

+0

Nó không có lợi thế chút nào; như tôi đã nói trong câu hỏi, tôi không muốn tạo chu kỳ này. Ngoài ra, tôi không bao giờ viết một loại giá trị có thể thay đổi được. Tuy nhiên, một trình định dạng tuần tự làm việc trên các đồ thị đối tượng tùy ý phải nhận thức được khả năng, và không nhập một vòng lặp vô hạn bằng cách giả định rằng các kiểu tham chiếu luôn tạo thành cây chứ không phải chu kỳ. Nó cũng có thể ảnh hưởng đến thứ tự các đối tượng phải được deserialized. –

+0

Ngẫu nhiên, các loại giá trị đóng hộp không thực sự là loại giá trị. Trong CLR, chúng được xử lý như các lớp, và chúng hoạt động giống như các lớp. Điều duy nhất khiến chúng đặc biệt là * các vị trí lưu trữ * có kiểu khai báo xuất phát từ kiểu giá trị sẽ giữ dữ liệu cho một mục thay vì tham chiếu đối tượng. – supercat

1

Thành thật mà nói, tôi đã không thử nó, nhưng xem nếu có tài sản Value trên một giao diện, và sau đó sử dụng giao diện như hộp của bạn cho phép bạn thay đổi bản thân đóng hộp chứ không phải là một bản sao mới.

Tôi mơ hồ cảm thấy như nó có thể, mặc dù tôi không chắc chắn lý do tại sao tôi nghĩ rằng. Hữu ích, huh?

0

Tôi không biết cấu trúc có thể triển khai giao diện. Điều đó có vẻ thực sự kỳ quái; những gì nó tốt cho? Là không thích cho các cấu trúc nói chung, hoặc cho các cấu trúc với các thuộc tính và phương pháp mà hành động theo chúng? Nó quá tệ .net không cho phép một người khai báo các thuộc tính và phương thức cấu trúc nhất định như các mutators, mà việc sử dụng các cấu trúc "ReadOnly" sẽ bị cấm.

+1

Re: giao diện và cấu trúc: tốt cho cùng một lý do giao diện hữu ích trên các loại tham chiếu - cho phép bạn chỉ định giao diện lập trình không quan tâm đến loại cơ bản. Một kiểu giá trị khá hợp lý có thể triển khai IComparable và IEquatable và cho phép các lớp sưu tập tạo ra các giả định về kiểu mà chúng sẽ không thể thực hiện được. – siride

+0

Tôi thấy quan điểm của bạn về iComparable và iEquatable. Tôi đoán vấn đề là không có cách nào để gắn cờ các phương thức làm biến đổi một đối tượng khỏi những đối tượng không làm. Không phải điều đó sẽ không cho phép mọi người "lừa gạt", nhưng nó sẽ tránh được hầu hết các 'gotchas' ngẫu nhiên. – supercat

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