Najważniejszą różnicą między a classa jest structto, co dzieje się w następującej sytuacji:
Thing thing1 = new Thing ();
thing1.somePropertyOrField = 5;
Rzecz rzecz 2 = rzecz 1;
thing2.somePropertyOrField = 9;
Jaki powinien być wpływ ostatniego stwierdzenia thing1.somePropertyOrField? Jeśli Thingstruct i somePropertyOrFieldjest odsłoniętym polem publicznym, obiekty thing1i thing2zostaną „oderwane” od siebie, więc to ostatnie zdanie nie będzie miało wpływu thing1. Jeśli Thingjest klasą, wtedy thing1i thing2będą do siebie przywiązane, a więc ta ostatnia instrukcja zapisze thing1.somePropertyOrField. Należy użyć struktury w przypadkach, w których poprzednia semantyka miałaby większy sens, i należy użyć klasy w przypadkach, w których druga semantyka miałaby większy sens.
Zauważ, że chociaż niektórzy ludzie radzą, że chęć zrobienia czegoś zmiennego jest argumentem przemawiającym za tym, że jest to klasa, sugerowałbym, że jest odwrotnie: jeśli coś, co istnieje w celu przechowywania niektórych danych, będzie podlegać zmianom, i jeśli nie będzie oczywiste, czy instancje są dołączone do czegokolwiek, rzecz powinna być strukturą (prawdopodobnie z odsłoniętymi polami), aby wyjaśnić, że instancje nie są dołączone do niczego innego.
Rozważmy na przykład stwierdzenia:
Osoba somePerson = myPeople.GetPerson („123-45-6789”);
somePerson.Name = "Mary Johnson"; // Był „Mary Smith”
Czy drugie zdanie zmieni informacje w nim przechowywane myPeople? Jeśli Personjest strukturą pola narażonego, nie będzie, a fakt, że nie będzie oczywistą konsekwencją bycia strukturą pola narażonego ; jeśli Personjest strukturą i chce się zaktualizować myPeople, to oczywiście trzeba coś zrobić myPeople.UpdatePerson("123-45-6789", somePerson). Jeśli Personjest to klasa, może być znacznie trudniej ustalić, czy powyższy kod nigdy nie zaktualizuje zawartości MyPeople, zawsze ją zaktualizuje, a czasem zaktualizuje.
Jeśli chodzi o pogląd, że struktury powinny być „niezmienne”, ogólnie nie zgadzam się. Istnieją uzasadnione przypadki użycia „niezmiennych” struktur (gdzie niezmienniki są wymuszane w konstruktorze), ale wymaganie, aby cała struktura musiała zostać przepisana za każdym razem, gdy jakakolwiek część jej zmian jest niewygodna, marnotrawna i bardziej skłonna do powodowania błędów niż po prostu ujawnianie pola bezpośrednio. Na przykład rozważmy PhoneNumberstrukturę, której pola obejmują między innymi, AreaCodei Exchange, i załóżmy, że ma List<PhoneNumber>. Następujący efekt powinien być dość wyraźny:
for (int i = 0; i <myList.Count; i ++)
{
PhoneNumber theNumber = myList [i];
if (theNumber.AreaCode == "312")
{
string newExchange = "";
if (new312to708Exchanges.TryGetValue (theNumber.Exchange), out newExchange)
{
theNumber.AreaCode = "708";
theNumber.Exchange = newExchange;
myList [i] = theNumber;
}
}
}
Zauważ, że nic w powyższym kodzie nie wie ani nie troszczy się o żadne pola PhoneNumberinne niż AreaCodei Exchange. Gdyby PhoneNumberbył tak zwaną „niezmienną” strukturą, konieczne byłoby albo dostarczenie withXXmetody dla każdego pola, która zwróciłaby nową instancję struktury, która posiadałaby przekazaną wartość we wskazanym polu, albo byłaby konieczna dla kodu takiego jak wyżej, aby wiedzieć o każdym polu w strukturze. Niezupełnie atrakcyjne.
BTW, istnieją co najmniej dwa przypadki, w których struktury mogą zasadnie zawierać odniesienia do typów zmiennych.
- Semantyka struktury wskazuje, że przechowuje ona tożsamość przedmiotowego obiektu, a nie skrót do przechowywania właściwości obiektu. Na przykład `KeyValuePair` przechowuje tożsamości niektórych przycisków, ale nie oczekuje się, że będą przechowywać trwałe informacje o pozycjach tych przycisków, stanach podświetlenia itp.
- Struktura wie, że posiada jedyne odniesienie do tego obiektu, nikt inny nie otrzyma odniesienia, a wszelkie mutacje, które kiedykolwiek zostaną wykonane na tym obiekcie, zostaną wykonane, zanim odniesienie do niego zostanie zapisane w dowolnym miejscu.
W poprzednim scenariuszu TOŻSAMOŚĆ obiektu będzie niezmienna; w drugim przypadku klasa zagnieżdżonego obiektu może nie wymuszać niezmienności, ale struktura przechowująca odwołanie to zrobi.