Properti otomatis C # 3.0 - berguna atau tidak? [Tutup]

155

Catatan: Ini diposting ketika saya memulai C #. Dengan pengetahuan 2014, saya benar-benar dapat mengatakan bahwa properti otomatis adalah salah satu hal terbaik yang pernah terjadi pada bahasa C #.

Saya terbiasa membuat properti saya di C # menggunakan bidang pribadi dan publik:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Sekarang, dengan .NET 3.0, kami mendapatkan properti otomatis:

public string Title { get; set; }

Saya tahu ini lebih merupakan pertanyaan filosofis / subyektif, tetapi apakah ada alasan untuk menggunakan properti otomatis ini kecuali dari menyimpan lima baris kode untuk setiap bidang? Keluhan pribadi saya adalah bahwa properti itu menyembunyikan barang-barang dari saya, dan saya bukan penggemar sihir hitam.

Bahkan, bidang pribadi yang tersembunyi bahkan tidak muncul di debugger, yang OK karena fakta bahwa fungsi get / set tidak melakukan apa-apa. Tetapi ketika saya ingin benar-benar mengimplementasikan beberapa logika pengambil / penyetel, saya tetap harus menggunakan pasangan pribadi / publik.

Saya melihat manfaat bahwa saya menyimpan banyak kode (satu vs enam baris) tanpa kehilangan kemampuan untuk mengubah logika pengambil / penyetel nanti, tapi sekali lagi saya sudah bisa melakukannya dengan hanya mendeklarasikan bidang publik "Public string Title" tanpa kebutuhan {get; set; } blok, bahkan menyimpan lebih banyak kode.

Jadi, apa yang saya lewatkan di sini? Mengapa ada orang yang benar-benar ingin menggunakan properti otomatis?

Michael Stum
sumber
86
"Keluhan pribadiku adalah bahwa properti itu menyembunyikan barang dariku, dan aku bukan penggemar sihir hitam." Hah? Anda sadar bahwa kompiler menyembunyikan satu ton dari Anda sepanjang waktu, bukan? Kecuali jika Anda menulis rakitan (atau lebih tepatnya, angka 1 dan 0 yang sebenarnya untuk kode Anda), SEMUA yang Anda tulis menyembunyikan barang-barang dari Anda.
Charles Boyung

Jawaban:

118

Kami menggunakannya sepanjang waktu di Stack Overflow.

Anda juga mungkin tertarik dalam diskusi tentang Properties vs Variabel Publik . IMHO itulah yang merupakan reaksi terhadap hal ini, dan untuk tujuan itu, sangat bagus.

Jeff Atwood
sumber
62

Ya, itu hanya menyimpan kode. Lebih mudah dibaca jika Anda memiliki banyak. Mereka lebih cepat menulis dan lebih mudah dirawat. Menyimpan kode selalu merupakan tujuan yang baik.

Anda dapat mengatur cakupan yang berbeda:

public string PropertyName { get; private set; }

Sehingga properti hanya bisa diubah di dalam kelas. Ini tidak benar-benar berubah karena Anda masih dapat mengakses setter pribadi melalui refleksi.

Pada C # 6 Anda juga dapat membuat readonlyproperti benar - yaitu properti tidak dapat diubah yang tidak dapat diubah di luar konstruktor:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

Pada waktu kompilasi itu akan menjadi:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

Di kelas yang tidak bisa diubah dengan banyak anggota, ini menyimpan banyak kode berlebih.

Keith
sumber
"Jadi, kamu tidak kehilangan fungsionalitas apa pun." bagaimana Anda men-debug mereka?
wal
2
@wal - apa yang bisa di-debug? Dari sudut pandang itu Anda pada dasarnya berurusan dengan variabel anggota.
Keith
6
@wal - Anda dapat meletakkan breakpoint pada mereka, sama seperti Anda dapat mengakses variabel anggota, Anda tidak bisa melangkah ke dalamnya. Tapi mengapa kamu mau? Apa yang sebenarnya dilakukan oleh properti otomatis itu sepele dan otomatis, jika Anda memiliki bug yang merupakan tempat yang sangat tidak mungkin.
Keith
3
kita mungkin perlu mengambil ini di luar Keith. :)
wal
1
Tapi ok, anggap Anda memiliki banyak panggilan setter ke myObj.Title ... Anda ingin melihat di mana nilai berubah dari "teks" menjadi nol, yaitu breakpoint bersyarat. bagaimana kamu mencapai itu? Anda bahkan tidak dapat menetapkan breakpoint pada setter
wal
45

Tiga kerugian besar untuk menggunakan bidang alih-alih properti adalah:

  1. Anda tidak bisa menyatukan data ke bidang sedangkan Anda bisa ke properti
  2. Jika Anda mulai menggunakan bidang, Anda tidak dapat nanti (dengan mudah) mengubahnya ke properti
  3. Ada beberapa atribut yang bisa Anda tambahkan ke properti yang tidak bisa Anda tambahkan ke bidang
lomaxx
sumber
7
"Jika Anda mulai menggunakan bidang, Anda tidak dapat nanti (dengan mudah) mengubahnya ke properti", maaf tapi mengapa?
Homam
6
@Homam Terutama, setiap kode konsumen yang menggunakan refleksi pada bidang Anda akan rusak, karena mereka harus beralih dari menggunakan FieldInfo ke PropertyInfo.
WCWedin
8
@Homam Juga, mengubah bidang ke properti akan merusak kompatibilitas biner, yang mengharuskan semua konsumen bidang untuk mengkompilasi ulang.
Odrade
1
Selain masalah kompilasi & refleksi, sangat mudah untuk merangkum bidang menggunakan Visual Studio: Ctrl-R + E akan memungkinkan Anda untuk mengubah bidang menjadi properti dengan getter / setter yang sesuai. (atau klik kanan bidang, faktor ulang, enkapsulasi bidang).
JoeBrockhaus
Bidang @Hommam adalah lvalues ​​(itu variabel), dan properti tidak. Hal-hal yang mungkin telah dikompilasi saat bidang mungkin tidak saat itu adalah properti.
Tandai
29

Saya pribadi suka properti otomatis. Apa yang salah dengan menyimpan baris kode? Jika Anda ingin melakukan hal-hal dalam getter atau setter, tidak ada masalah untuk mengubahnya menjadi properti normal nanti.

Seperti yang Anda katakan, Anda bisa menggunakan bidang, dan jika Anda ingin menambahkan logika untuk nanti, Anda akan mengubahnya menjadi properti. Tapi ini mungkin menimbulkan masalah dengan penggunaan refleksi (dan mungkin di tempat lain?).

Juga properti memungkinkan Anda untuk mengatur tingkat akses yang berbeda untuk pengambil dan penyetel yang tidak dapat Anda lakukan dengan bidang.

Saya kira itu sama dengan kata kunci var. Masalah preferensi pribadi.

sinar
sumber
29

Dari Bjarne Stroustrup, pencipta C ++:

Saya sangat tidak suka kelas dengan banyak fungsi get and set. Itu sering merupakan indikasi bahwa seharusnya tidak menjadi kelas di tempat pertama. Itu hanya struktur data. Dan jika itu benar-benar struktur data, buatlah struktur data.

Dan tahukah Anda? Dia benar. Seberapa sering Anda hanya membungkus bidang pribadi dalam get and set, tanpa benar-benar melakukan apa pun dalam get / set, hanya karena itu adalah "berorientasi objek" yang harus dilakukan. Ini adalah solusi Microsoft untuk masalah ini; mereka pada dasarnya adalah bidang publik yang dapat Anda ikat.

Giovanni Galbo
sumber
2
Saya pikir ini seharusnya memiliki lebih banyak poin. Terlalu banyak orang melihat properti otomatis sebagai lampu hijau untuk menulis kelas yang dienkapsulasi secara mengerikan (atau tidak dienkapsulasi sama sekali) yang sedikit lebih dari bidang publik yang dimuliakan. Tentu saja ini lebih merupakan masalah dengan bagaimana orang menggunakan alat daripada dengan alat itu sendiri, tapi saya pikir ini penting untuk disebutkan ketika membahas properti secara umum.
sara
18

Satu hal yang tampaknya tidak disebutkan oleh siapa pun adalah bagaimana sifat-otomatis sayangnya tidak berguna untuk objek yang tidak dapat diubah (biasanya struct yang tidak dapat diubah). Karena untuk itu Anda benar-benar harus melakukan:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(tempat bidang diinisialisasi dalam konstruktor melalui parameter yang diteruskan, dan kemudian hanya dibaca.)

Jadi ini memiliki kelebihan dibanding yang sederhana get/ private setautoproperti.

Domenik
sumber
Jika Anda memiliki struct yang mengubah properti apa pun di atasnya, akan menghasilkan struct baru. Ini hanya akan menjadi masalah jika Anda menginginkan jenis referensi yang tidak dapat diubah secara internal - Saya tidak dapat melihat alasan mengapa Anda membutuhkannya.
Keith
@Keith: Kalimat pertama Anda tampaknya tidak benar secara faktual.
Domenic
3
Tidakkah akan public string Title { get; private set; }menghasilkan hal yang persis sama? Anda akan dapat mengubahnya dari dalam kelas maka tentu saja, tetapi jika Anda melakukannya Anda memiliki masalah lain ...: p
Svish
2
@Svish - dengan argumen itu kata kunci yang hanya bisa dibaca dalam C # tidak boleh digunakan karena penggunaannya akan berarti bahwa kami menyembunyikan "masalah yang berbeda" ini
Zaid Masud
2
Maksud saya, dari tampilan API luar, tidak akan ada banyak perbedaan. Jadi, properti otomatis dapat digunakan jika diinginkan. Hal terbaik tentu saja adalah jika Anda bisa melakukan sesuatu sepertipublic string Title { get; private readonly set; }
Svish
12

Saya selalu membuat properti alih-alih bidang publik karena Anda bisa menggunakan properti dalam definisi antarmuka, Anda tidak bisa menggunakan bidang publik dalam definisi antarmuka.

Theo
sumber
8

Properti otomatis adalah sihir hitam seperti yang lainnya di C #. Setelah Anda memikirkannya dalam hal kompilasi ke IL daripada diperluas ke properti C # normal terlebih dahulu itu jauh lebih sedikit ilmu hitam daripada banyak konstruksi bahasa lainnya.

ICR
sumber
5

Saya menggunakan properti otomatis sepanjang waktu. Sebelum C # 3 saya tidak bisa diganggu dengan semua pengetikan dan hanya menggunakan variabel publik saja.

Satu-satunya hal yang saya lewatkan adalah dapat melakukan ini:

public string Name = "DefaultName";

Anda harus mengubah default ke konstruktor Anda dengan properti. membosankan :-(

Orion Edwards
sumber
4
Dengan inisialisasi properti otomatis dari C # 6 Anda akan segera dapat melakukan ini: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz
5

Saya pikir setiap konstruksi yang intuitif DAN mengurangi garis kode adalah nilai tambah yang besar.

Jenis-jenis fitur itulah yang membuat bahasa seperti Ruby begitu kuat (fitur itu dan dinamis, yang juga membantu mengurangi kelebihan kode).

Ruby telah memiliki ini selama:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter
Mike Stone
sumber
2

Satu-satunya masalah yang saya miliki dengan mereka adalah bahwa mereka tidak cukup jauh. Rilis yang sama dari kompiler yang menambahkan properti otomatis, menambahkan metode parsial. Mengapa mereka tidak menggabungkan keduanya adalah di luar jangkauan saya. "Parsial Pada <PropertyName> Berubah" yang sederhana akan membuat hal-hal ini benar-benar bermanfaat.

David Wengier
sumber
Anda dapat menempatkan beberapa metode parsial di dalam metode lain. Membuat pola-otomatis semacam itu bagi mereka akan membingungkan.
Matthew Whited
2

Sederhana, pendek, dan jika Anda ingin membuat implementasi nyata di dalam tubuh properti di suatu tempat, itu tidak akan merusak antarmuka eksternal tipe Anda.

Sesimpel itu.

Omer van Kloeten
sumber
1

Satu hal yang perlu diperhatikan di sini adalah bahwa, menurut pemahaman saya, ini hanyalah gula sintaksis pada ujung C # 3.0, yang berarti bahwa IL yang dihasilkan oleh kompiler adalah sama. Saya setuju tentang menghindari ilmu hitam, tetapi semua sama, lebih sedikit garis untuk hal yang sama biasanya merupakan hal yang baik.

pbh101
sumber
1

Menurut pendapat saya, Anda harus selalu menggunakan properti otomatis alih-alih bidang publik. Yang mengatakan, inilah kompromi:

Mulailah dengan bidang internal menggunakan konvensi penamaan yang akan Anda gunakan untuk properti. Ketika Anda pertama kali juga

  • memerlukan akses ke bidang dari luar rakitannya, atau
  • perlu melampirkan logika ke pengambil / penyetel

Melakukan hal ini:

  1. ganti nama bidang
  2. jadikan ini pribadi
  3. tambahkan properti publik

Kode klien Anda tidak perlu diubah.

Namun, suatu hari nanti, sistem Anda akan tumbuh dan Anda akan menguraikannya menjadi rakitan terpisah dan beberapa solusi. Ketika itu terjadi, setiap bidang yang terbuka akan kembali menghantui Anda karena, seperti yang disebutkan Jeff, mengubah bidang publik menjadi properti publik adalah melanggar perubahan API .

ESV
sumber
0

Saya menggunakan CodeRush, ini lebih cepat daripada properti otomatis.

Untuk melakukan ini:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Membutuhkan total delapan penekanan tombol.

Brian Leahy
sumber
5
Jika saya menahan CTRL dan V, saya bisa menempelkan banyak dan banyak hal, / sangat cepat /, tapi itu tidak membuatnya 'lebih baik'. Bagaimana ini menjawab pertanyaan awal?
JBRWilkinson
0

Nah dengan potongan kode properti-otomatis dengan nama yang sama akan menjadi tujuh penekanan tombol total;)

ICR
sumber
0

@Domenic: Saya tidak mengerti .. tidak bisakah Anda melakukan ini dengan properti-otomatis ?:

public string Title { get; }

atau

public string Title { get; private set; }

Apakah ini yang Anda maksud?

Andrei Rînea
sumber
Anda bisa (yang terakhir; yang pertama tidak akan mengkompilasi), tetapi kemudian bidang tidak berubah di dalam objek Anda.
Domenic
Kata hati-hati, hanya struct yang tidak berubah ketika ditandai hanya dibaca, kelas hanya tidak dapat ditugaskan.
Guvante
0

Keluhan terbesar saya dengan properti otomatis adalah bahwa mereka dirancang untuk menghemat waktu, tetapi saya sering menemukan saya harus mengembangkannya menjadi properti yang penuh sesak nanti.

Apa yang VS2008 hilang adalah sebuah refactor Auto-Property yang meledak .

Fakta kami memiliki refactor bidang enkapsulasi membuat cara saya bekerja lebih cepat untuk hanya menggunakan bidang publik.

Johnno Nolan
sumber