İzlenecek genel kural, yapıların bir zamanlar yaratılamayan, küçük, basit (tek seviyeli) ilgili özellik koleksiyonları olması gerektiğidir; başka bir şey için bir sınıf kullanın.
C #, yapıların ve sınıfların, tanımlayıcı anahtar kelimeden başka bildirimde açık bir farklılığı olmaması nedeniyle iyidir; bu nedenle, bir yapıyı bir sınıfa "yükseltmeniz" veya bir sınıfı bir yapıya dönüştürmenin "gerektiğini" düşünüyorsanız, bu anahtar kelimeyi değiştirmenin basit bir meselesidir (başka bir kaç tane var; yapılar elde edilemez) başka herhangi bir sınıf veya yapı türünden ve açıkça varsayılan bir parametresiz yapıcı tanımlayamazlar).
"Çoğunlukla" diyorum, çünkü yapılar hakkında bilinmesi gereken en önemli şey, onlar değer türleri oldukları için, onlara sınıflar gibi davranmaları (referans türleri) bir buçuk acı verebilir. Özellikle, bir yapının özelliklerini değiştirilebilir hale getirmek, beklenmeyen davranışlara neden olabilir.
Örneğin, iki özelliğe sahip bir SimpleClass sınıfınız olduğunu varsayalım, A ve B. Bu sınıfın bir kopyasını başlatıyorsunuz, A ve B'yi başlatıyorsunuz ve örneği başka bir yönteme aktarıyorsunuz. Bu yöntem, A ve B'yi daha da değiştirir. Çağıran işlevde (örneği oluşturan yöntem), örneğinizin A ve B'si, çağrılan yöntem tarafından kendilerine verilen değerlere sahip olacaktır.
Şimdi, onu bir yapı haline getirdin. Özellikler hala değişkendir. Aynı işlemleri daha önce olduğu gibi aynı sözdizimiyle gerçekleştiriyorsunuz, ancak şimdi A ve B'nin yeni değerleri, yöntemi çağırdıktan sonra görünmüyor. Ne oldu? Sınıfınız şimdi bir yapı, yani bir değer türü. Bir yönteme değer türü iletirseniz, varsayılan (bir çıkış veya ref anahtar sözcüğü olmadan) "değere göre" geçirmektir; Örneğin sığ bir kopyası yöntem tarafından kullanılmak üzere yaratılır ve daha sonra yöntem ilk örneği bozulmadan bırakıldığında yok edilir.
Yapınızın bir üyesi olarak bir referans türüne sahip olsaydınız, bu daha da kafa karıştırıcı hale gelirdi ( neredeyse tüm durumlarda , izin verilmez, ancak son derece kötü bir uygulama); sınıf klonlanmayacak (yalnızca yapıya referansta bulunacak), bu nedenle yapıya yapılan değişiklikler orijinal nesneyi etkilemeyecek, ancak yapıya ait alt sınıftaki değişiklikler WILL'i arama kodundan etkileyecektir. Bu, değişken yapıları çok tutarsız durumlara koyabilir, bu da gerçek sorunun olduğu yerden çok uzun bir süre önce hatalara neden olabilir.
Bu nedenle, C # üzerindeki hemen hemen her otorite yapılarınızı her zaman değiştirilemez kıldığını söyler; tüketicinin mülklerin değerlerini yalnızca bir nesnenin yapımında belirtmesine izin vermek ve bu vakanın değerlerini değiştirmek için hiçbir zaman hiçbir yol belirtmemek. Salt okunur alanlar veya yalnızca alma özellikleri kuraldır. Tüketici değeri değiştirmek isterse, eskisinin değerlerine dayanarak yeni bir nesne yaratabilir, istedikleri değişikliklerle veya aynı şeyi yapacak bir yöntem çağırabilir. Bu, onları yapınızın tek bir örneğine, bölünemez ve diğerlerinden farklı (ancak muhtemelen eşdeğer) tek bir kavramsal "değer" olarak muamele etmeye zorlar. Tipinize göre depolanan bir "değer" üzerinde işlem yaparlarsa, başlangıç değerlerinden farklı yeni bir "değer" alırlar,
İyi bir örnek için DateTime türüne bakın. Bir DateTime örneğinin alanlarından herhangi birini doğrudan atayamazsınız; ya yeni bir tane oluşturmanız ya da mevcut olanın üzerine yeni bir örnek üretecek bir yöntem çağırmanız gerekir. Bunun nedeni, tarih ve saatin, 5 sayısı gibi bir "değer" olmasıdır ve 5 sayısındaki değişiklik, 5 olmayan yeni bir değere yol açar. çünkü ona 1 tane ekledin. DateTimes aynı şekilde çalışır; 12:00, bir dakika eklerseniz, 12:01 "haline gelmez" yerine 12:01 den farklı bir değer elde edersiniz. Bu, türünüze ilişkin mantıksal bir durum ise (.NET'te yerleşik olmayan iyi kavramsal örnekler Para, Mesafe, Ağırlık ve işlemlerin değerin tüm bölümlerini göz önünde bulundurması gereken bir UOM diğer miktarlarıdır), daha sonra bir yapı kullanın ve buna göre tasarlayın. Bir nesnenin alt öğelerinin bağımsız olarak değişken olması gereken diğer birçok durumda, bir sınıf kullanın.