Cấu trúc là một kiểu giá trị, vì vậy nếu tôi gán một cấu trúc cho cấu trúc khác, các trường của nó sẽ được sao chép trong cấu trúc thứ hai. Nhưng, điều gì sẽ xảy ra nếu một số trường của cấu trúc là một kiểu tham chiếu?Cấu trúc chứa các kiểu tham chiếu
public struct MyIPEndPoint
{
public String IP;
public UInt16 Port;
public MyIPEndPoint(String ipAddress, UInt16 portNumber)
{
IP = ipAddress;
Port = portNumber;
}
public override string ToString()
{
return IP+":"+Port;
}
}
...
static int Main(string[] args)
{
MyIPEndPoint address1 = new MyIPEndPoint("127.0.0.1", 8080);
MyIPEndPoint address2 = address1;
address2.IP = "255.255.255.255";
address2.Port = 9090;
Console.WriteLine(address1);
Console.WriteLine(address2);
}
Đầu ra là:
127.0.0.1:8080
255.255.255.255:9090
Tại sao IP
(một chuỗi, đó là một loại tài liệu tham khảo) của address1
không thay đổi? Hành vi tương tự xảy ra nếu tôi thay thế string
bằng IPAddress
để đại diện cho IP trong phạm vi MyIPEndPoint
: mặc dù IPAddress
là một lớp (là loại tham chiếu), nó không hoạt động như một loại tham chiếu. Tại sao?
Thật vậy, nếu tôi quấn string
đại diện cho IP bằng cách sử dụng một lớp đơn giản mới MyIP
, thay đổi hành vi.
public class MyIP
{
public string IpAsString;
public MyIP(string s)
{
IpAsString = s;
}
public override string ToString()
{
return IpAsString;
}
}
Tất nhiên bạn cũng nên điều chỉnh MyIPEndPoint
struct theo cách sau:
public struct MyIPEndPoint
{
public MyIP IP; // modification
public UInt16 Port;
public MyIPEndPoint(String ipAddress, UInt16 portNumber)
{
IP = new MyIP(ipAddress); // modification
Port = portNumber;
}
public override string ToString()
{
return IP+":"+Port;
}
}
Cuối cùng trong Main
tôi đã thay đổi chỉ một tuyên bố:
MyIPEndPoint address1 = new MyIPEndPoint("127.0.0.1", 8080);
MyIPEndPoint address2 = address1;
address2.IP.IpAsString = "255.255.255.255"; // modification
address2.Port = 9090;
Console.WriteLine(address1);
Console.WriteLine(address2);
Bây giờ đầu ra là:
255.255.255.255:8080
255.255.255.255:9090
Tôi đã mong đợi kết quả này trong trường hợp đầu tiên. Tại sao trong trường hợp đầu tiên tham chiếu không hoạt động như mong đợi?
Tôi hiểu lý do: nói cách khác, nếu IPAddress có trường công khai, tôi có thể tạo lại kết quả tương tự. – enzom83
Nếu bạn có thể sửa đổi trạng thái của đối tượng được tham chiếu bởi biến chuỗi (hoặc trường) mà không thực sự ghi đè tham chiếu, bạn có thể quan sát các thay đổi trong cả hai cấu trúc. Nhưng bạn không sửa đổi trạng thái (và bạn không thể, ít nhất là không có trong mã an toàn), bạn ghi đè hoàn toàn tham chiếu thông qua chuyển nhượng lại. Trong lần thứ hai, bạn đã sửa đổi trạng thái của đối tượng đã được tham chiếu bởi cả hai cá thể struct. Giá trị của IP, * tham chiếu đến đối tượng *, không thay đổi, vì vậy bạn đã quan sát kết quả trong cả hai. –
Tôi không chắc chắn tuyên bố của bạn là đúng, "Nó không có gì để làm với thực tế là chuỗi là một loại tài liệu tham khảo hoặc bất kỳ quy tắc đặc biệt hoặc bất kỳ đề nghị bất biến." Nếu một chuỗi là một kiểu tham chiếu thông thường, thì việc thay đổi giá trị thông qua một tham chiếu sẽ thay đổi nó cho tất cả các tham chiếu. Nhưng chuỗi là một kiểu tham chiếu không thay đổi, có nghĩa là nó hoạt động giống như một kiểu giá trị. http://stackoverflow.com/questions/636932/in-c-why-is-string-a-reference-type-that-behaves-like-a-value-type. Tuyên bố của bạn là đúng nếu bạn giả sử "=" luôn có nghĩa là chỉ định tham chiếu, nhưng với một số thì nó có nghĩa là giá trị sao chép. – BlueMonkMN