Структура - тип значения, поэтому, если я назначу структуру другой структуре, ее поля будут скопированы во второй структуре. Но что произойдет, если некоторые поля структуры являются ссылочным типом?Структуры, содержащие ссылочные типы
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);
}
Выход:
127.0.0.1:8080
255.255.255.255:9090
Почему IP
(строка, которая является ссылкой типа) address1
не меняется? Такое же поведение возникает, если я заменяю string
на IPAddress
, чтобы представить IP в пределах MyIPEndPoint
: хотя IPAddress
- это класс (ссылочный тип), он не ведет себя как ссылочный тип. Зачем?
Действительно, если я обертываю string
, которые представляют IP-адрес, используя новый простой класс MyIP
, поведение изменяется.
public class MyIP
{
public string IpAsString;
public MyIP(string s)
{
IpAsString = s;
}
public override string ToString()
{
return IpAsString;
}
}
Конечно, вы также должны настроить MyIPEndPoint
-структуру следующим образом:
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;
}
}
Наконец в Main
я изменил только заявление:
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);
Теперь выход есть:
255.255.255.255:8080
255.255.255.255:9090
Я ожидал этот выход в первом случае. Почему в первом случае ссылка не ведет себя как ожидалось?
Я понимаю причину: другими словами, если IPAddress публиковал свои поля, я мог бы воспроизвести тот же результат. – enzom83
Если вы можете изменить состояние объекта, на которое ссылается строковая переменная (или поле), фактически не перезаписывая ссылку, вы можете наблюдать изменения в обеих структурах. Но вы не изменяли состояние (и вы не можете, по крайней мере, не в безопасном коде), вы полностью переписываете ссылку посредством переназначения. Во втором случае вы изменили состояние объекта, на который ссылались оба экземпляра struct. Значение IP, * ссылка на объект * не изменилось, поэтому вы наблюдали результаты в обоих. –
Я не уверен, что ваше утверждение верно: «Это не имеет никакого отношения к тому факту, что строка является ссылочным типом или любыми специальными правилами или любым предложением неизменности». Если строка была обычным ссылочным типом, то изменение значения с помощью одной ссылки изменило бы ее для всех ссылок. Но строка - это неизменный ссылочный тип, что означает, что он ведет себя как тип значения. http://stackoverflow.com/questions/636932/in-c-why-is-string-a-reference-type-that-behaves-like-a-value-type. Ваше утверждение верно, если вы предполагаете, что «=» всегда означает назначение ссылки, но для кого-то это означает значение копирования. – BlueMonkMN