public class MyClass
{
public object Prop1 { get; set; }
public object Prop2 { get; set; }
public object Prop3 { get; set; }
}
Misalkan saya memiliki objek myObject
dari MyClass
dan saya harus mengatur ulang sifat-sifatnya, adalah lebih baik untuk membuat objek baru atau menetapkan kembali masing-masing properti? Asumsikan saya tidak memiliki penggunaan tambahan dengan instance lama.
myObject = new MyClass();
atau
myObject.Prop1 = null;
myObject.Prop2 = null;
myObject.Prop3 = null;
c#
object-oriented
construction
Lonceng
sumber
sumber
Suppose I have an object myObject of MyClass and I need to reset its properties
- Jika mengatur ulang properti objek Anda diperlukan atau jika berguna untuk memodelkan domain masalah, mengapa tidak membuatreset()
metode untuk MyClass. Lihat jawaban HarrisonPaine di bawah iniJawaban:
Membuat instance objek baru selalu lebih baik, maka Anda memiliki 1 tempat untuk menginisialisasi properti (konstruktor) dan dapat dengan mudah memperbaruinya.
Bayangkan Anda menambahkan properti baru ke kelas, Anda lebih suka memperbarui konstruktor daripada menambahkan metode baru yang juga menginisialisasi ulang semua properti.
Sekarang, ada beberapa kasus di mana Anda mungkin ingin menggunakan kembali objek, yang mana properti sangat mahal untuk diinisialisasi ulang dan Anda ingin menyimpannya. Namun ini akan lebih spesialis, dan Anda akan memiliki metode khusus untuk menginisialisasi ulang semua properti lainnya. Anda masih ingin membuat objek baru terkadang bahkan untuk situasi ini.
sumber
myObject = new MyClass(oldObject);
. Meskipun ini akan menyiratkan salinan yang tepat dari objek asli dalam contoh baru.new MyClass(oldObject)
ini adalah solusi terbaik untuk kasus-kasus di mana inisialisasi mahal.Anda tentu harus lebih suka membuat objek baru di sebagian besar kasus. Masalah dengan menetapkan kembali semua properti:
A
dan kelasB
sama-sama lulus instance dari kelasC
maka mereka harus tahu apakah mereka akan pernah lulus contoh yang sama, dan jika demikian apakah yang lain masih menggunakannya. Ini erat pasangan kelas yang sebaliknya tidak punya alasan untuk menjadi.Fraction
kelas dengan pembilang dan penyebut, dan ingin memastikan bahwa itu selalu dikurangi (yaitu gcd pembilang dan penyebutnya adalah 1). Ini tidak mungkin dilakukan dengan baik jika Anda ingin orang-orang mengatur pembilang dan penyebutnya secara publik, karena mereka dapat bertransisi melalui negara yang tidak valid untuk berpindah dari satu keadaan yang valid ke yang lain. Misalnya 1/2 (valid) -> 2/2 (tidak valid) -> 2/3 (valid).Ini semua adalah masalah yang cukup signifikan. Dan apa yang Anda dapatkan sebagai imbalan atas kerja ekstra yang Anda buat adalah ... tidak ada. Membuat instance objek adalah, secara umum, sangat murah, sehingga manfaat kinerja hampir selalu dapat diabaikan.
Seperti jawaban lain yang disebutkan, satu-satunya kinerja waktu yang mungkin menjadi perhatian yang relevan adalah jika kelas Anda mengerjakan pekerjaan konstruksi yang sangat mahal. Tetapi bahkan dalam kasus itu, agar teknik ini berfungsi, Anda harus dapat memisahkan bagian yang mahal dari properti yang Anda atur ulang, sehingga Anda dapat menggunakan pola bobot terbang atau yang serupa.
Sebagai catatan tambahan, beberapa masalah di atas dapat dikurangi sedikit dengan tidak menggunakan setter dan sebaliknya memiliki
public Reset
metode di kelas Anda yang mengambil parameter yang sama dengan konstruktor. Jika karena alasan tertentu Anda memang ingin turun rute reset ini, itu mungkin cara yang lebih baik untuk melakukannya.Namun, kompleksitas tambahan dan pengulangan yang menambahkan, bersama dengan poin-poin di atas yang tidak dibahas, masih merupakan argumen yang sangat persuasif untuk tidak melakukannya, terutama ketika ditimbang dengan manfaat yang tidak ada.
sumber
Mengingat contoh yang sangat umum, sulit untuk mengatakannya. Jika "mengatur ulang properti" masuk akal semantik dalam kasus domain, itu akan lebih masuk akal bagi konsumen kelas Anda untuk menelepon
Dari
Saya TIDAK AKAN PERNAH meminta konsumen panggilan kelas Anda
Jika kelas mewakili sesuatu yang dapat diatur ulang, itu harus mengekspos fungsionalitas itu melalui
Reset()
metode, daripada mengandalkan memanggil konstruktor atau secara manual mengatur propertinya.sumber
Seperti yang disarankan Harrison Paine dan Brandin, saya akan menggunakan kembali objek yang sama dan memfaktisasi inisialisasi properti dalam metode Reset:
sumber
Jika pola penggunaan yang dimaksudkan untuk suatu kelas adalah bahwa satu pemilik akan menyimpan referensi untuk setiap instance, tidak ada kode lain yang akan menyimpan salinan referensi, dan itu akan sangat umum bagi pemilik untuk memiliki loop yang perlu, berkali-kali , " isi "contoh kosong, gunakan itu untuk sementara, dan jangan pernah membutuhkannya lagi (pertemuan kelas yang umum dengan kriteria seperti itu
StringBuilder
) maka mungkin berguna dari sudut pandang kinerja bagi kelas untuk memasukkan metode untuk mengatur ulang contoh ke seperti- Kondisi baru. Optimalisasi seperti itu sepertinya tidak akan bernilai banyak jika alternatifnya hanya membutuhkan pembuatan beberapa ratus contoh, tetapi biaya untuk membuat jutaan atau milyaran contoh objek dapat bertambah.Pada catatan terkait, ada beberapa pola yang dapat digunakan untuk metode yang perlu mengembalikan data dalam objek:
Metode menciptakan objek baru; mengembalikan referensi.
Metode menerima referensi ke objek yang bisa berubah, dan mengisinya.
Metode menerima variabel tipe referensi sebagai
ref
parameter dan menggunakan objek yang ada jika sesuai, atau mengubah variabel untuk mengidentifikasi objek baru.Pendekatan pertama seringkali paling mudah secara semantik. Yang kedua agak canggung di sisi panggilan, tetapi dapat menawarkan kinerja yang lebih baik jika penelepon akan sering dapat membuat satu objek dan menggunakannya ribuan kali. Pendekatan ketiga agak canggung semantik, tetapi dapat membantu jika suatu metode perlu mengembalikan data dalam sebuah array dan pemanggil tidak akan tahu ukuran array yang diperlukan. Jika kode panggilan menyimpan satu-satunya referensi ke array, menulis ulang referensi itu dengan referensi ke array yang lebih besar akan secara semantik setara dengan hanya membuat array lebih besar (yang merupakan perilaku yang diinginkan secara semantik). Meskipun menggunakan
List<T>
mungkin lebih baik daripada menggunakan array yang diubah ukurannya secara manual dalam banyak kasus, array struktur menawarkan semantik yang lebih baik dan kinerja yang lebih baik daripada daftar struktur.sumber
Saya pikir kebanyakan orang menjawab untuk menyukai membuat objek baru kehilangan skenario kritis: pengumpulan sampah (GC). GC dapat memiliki hit kinerja nyata dalam aplikasi yang menciptakan banyak objek (pikirkan game, atau aplikasi ilmiah).
Katakanlah saya memiliki pohon ekspresi yang mewakili ekspresi matematika, di mana di dalam simpul adalah simpul fungsi (ADD, SUB, MUL, DIV), dan simpul daun adalah simpul terminal (X, e, PI). Jika kelas simpul saya memiliki metode Evaluate (), kemungkinan akan memanggil anak-anak secara berulang dan mengumpulkan data melalui data node. Paling tidak, semua simpul daun perlu membuat objek Data dan kemudian mereka dapat digunakan kembali pada jalan menaiki pohon sampai nilai akhir dievaluasi.
Sekarang katakanlah saya memiliki ribuan pohon ini dan saya mengevaluasi mereka dalam satu lingkaran. Semua objek Data tersebut akan memicu GC dan menyebabkan kinerja, yang besar (hilangnya utilisasi CPU hingga 40% untuk beberapa proses di aplikasi saya - Saya telah menjalankan profiler untuk mendapatkan data).
Solusi yang memungkinkan? Gunakan kembali objek data tersebut dan panggil beberapa .Reset () pada mereka setelah Anda selesai menggunakannya. Node daun tidak akan lagi memanggil 'Data baru ()', mereka akan memanggil beberapa metode Pabrik yang menangani siklus hidup objek.
Saya tahu ini karena saya memiliki aplikasi yang telah mengenai masalah ini dan ini menyelesaikannya.
sumber