Dalam C #, apa yang membuat bidang berbeda dari properti, dan kapan bidang harus digunakan alih-alih properti?
Dalam C #, apa yang membuat bidang berbeda dari properti, dan kapan bidang harus digunakan alih-alih properti?
Jawaban:
Properti memperlihatkan bidang. Fields harus (hampir selalu) dirahasiakan ke kelas dan diakses melalui get dan set properti. Properti menyediakan tingkat abstraksi yang memungkinkan Anda untuk mengubah bidang sementara tidak mempengaruhi cara eksternal mereka diakses oleh hal-hal yang menggunakan kelas Anda.
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
@ Kent menunjukkan bahwa Properties tidak diperlukan untuk merangkum bidang, mereka bisa melakukan perhitungan pada bidang lain, atau melayani tujuan lain.
@ GSS menunjukkan bahwa Anda juga dapat melakukan logika lain, seperti validasi, ketika properti diakses, fitur lain yang bermanfaat.
string
, kontrak saya adalah: tetapkan karakter apa pun hingga ~ 2bil panjang. Jika ada properti DateTime
, kontrak saya adalah: tetapkan angka apa pun dalam batas DateTime, yang dapat saya cari. Jika pembuat menambahkan batasan pada setter, batasan itu tidak dikomunikasikan. Tetapi jika, sebagai gantinya, pencipta mengubah jenis dari string
menjadi Surname
, maka nama keluarga baru mereka mengkomunikasikan kendala, dan properti public Surname LastName
tidak memiliki validasi setter. Juga, Surname
dapat digunakan kembali.
Surname
, dalam contoh saya, dapat digunakan kembali, Anda tidak perlu khawatir nanti tentang menyalin / menempelkan validasi tersebut di setter properti ke tempat lain dalam kode. Atau bertanya-tanya apakah validasi nama keluarga ada di banyak tempat jika Anda pernah membuat perubahan pada aturan bisnis untuk nama keluarga. Lihat tautan yang saya poskan tentang Value Objects
Prinsip-prinsip pemrograman berorientasi objek mengatakan bahwa, kerja internal suatu kelas harus disembunyikan dari dunia luar. Jika Anda mengekspos bidang Anda pada dasarnya mengekspos implementasi internal kelas. Oleh karena itu kami membungkus bidang dengan Properti (atau metode dalam kasus Java) untuk memberi kami kemampuan untuk mengubah implementasi tanpa melanggar kode tergantung pada kami. Melihat seperti yang kita dapat menempatkan logika di Properti juga memungkinkan kita untuk melakukan logika validasi dll jika kita membutuhkannya. C # 3 memiliki gagasan autoproperties yang mungkin membingungkan. Ini memungkinkan kita untuk mendefinisikan Properti dan kompiler C # 3 akan menghasilkan bidang pribadi untuk kita.
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
public int myVar { get; set; }
sebenarnya diperjuangkan (dan saya menganggap itu alasannya) untuk setidaknya 50% hit yang didapat pertanyaan ini).
virtual
itu sendiri adalah bagian dari pemrograman berorientasi objek.
virtual
OOP per se. Ini adalah alat yang memungkinkan polimorfisme, yang merupakan salah satu alat utama yang MEMUNGKINKAN OOP. Ini bukan OOP dalam dan dari dirinya sendiri, dan tidak ada yang secara inheren OOP tentang autoproperti publik. Saya tidak akan menghitung hal-hal seperti refleksi atau penyatuan data yang terkait dengan OOP. Biasanya saya tidak akan terlalu jago tentang hal itu, tetapi jawabannya secara khusus menyebutkan prinsip-prinsip OO sebagai kekuatan pendorong di belakang contoh kode, dan saya tidak setuju dengan itu.
Perbedaan penting adalah bahwa antarmuka dapat memiliki properti tetapi tidak bidang. Ini, bagi saya, menggarisbawahi bahwa properti harus digunakan untuk mendefinisikan antarmuka publik kelas sementara bidang dimaksudkan untuk digunakan dalam cara kerja pribadi internal kelas. Sebagai aturan saya jarang membuat bidang publik dan juga saya jarang membuat properti non-publik.
Saya akan memberi Anda beberapa contoh menggunakan properti yang mungkin membuat roda gigi berputar:
Menggunakan Properti, Anda dapat meningkatkan acara, ketika nilai properti diubah (alias. PropertyChangedEvent) atau sebelum nilai diubah untuk mendukung pembatalan.
Ini tidak dimungkinkan dengan bidang (akses langsung ke).
public class Person {
private string _name;
public event EventHandler NameChanging;
public event EventHandler NameChanged;
public string Name{
get
{
return _name;
}
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
private void OnNameChanging(){
NameChanging?.Invoke(this,EventArgs.Empty);
}
private void OnNameChanged(){
NameChanged?.Invoke(this,EventArgs.Empty);
}
}
Karena banyak dari mereka telah menjelaskan dengan pro dan kontra teknis Properties
dan Field
, saatnya untuk masuk ke dalam contoh waktu nyata.
1. Properti memungkinkan Anda untuk mengatur tingkat akses hanya-baca
Pertimbangkan kasus dataTable.Rows.Count
dan dataTable.Columns[i].Caption
. Mereka berasal dari kelas DataTable
dan keduanya bersifat publik untuk kita. Perbedaan tingkat akses kepada mereka adalah bahwa kita tidak dapat menetapkan nilai dataTable.Rows.Count
tetapi kita dapat membaca dan menulis dataTable.Columns[i].Caption
. Apakah itu mungkin terjadi Field
? Tidak!!! Ini hanya bisa dilakukan dengan Properties
.
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
2. Properti di PropertyGrid
Anda mungkin pernah bekerja dengan Button
di Visual Studio. Sifat-sifatnya ditampilkan dalam PropertyGrid
sejenisnya Text
, Name
dll. Ketika kita seret dan jatuhkan tombol, dan ketika kita mengklik propertinya, itu akan secara otomatis menemukan kelas Button
dan filter Properties
dan menunjukkan bahwa di PropertyGrid
( di mana PropertyGrid
tidak akan ditampilkan Field
meskipun mereka publik).
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
Di PropertyGrid
, properti Name
dan Text
akan ditampilkan, tetapi tidak SomeProperty
. Mengapa??? Karena Properti dapat menerima Atribut . Itu tidak menunjukkan jika [Browsable(false)]
salah.
3. Dapat menjalankan pernyataan di dalam Properties
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
4. Hanya Properti yang dapat digunakan di Binding Source
Binding Source membantu kita mengurangi jumlah baris kode. Fields
tidak diterima oleh BindingSource
. Kita harus menggunakannya Properties
untuk itu.
5. Mode debugging
Anggap kita gunakan Field
untuk menyimpan nilai. Pada titik tertentu kita perlu men-debug dan memeriksa di mana nilai semakin nol untuk bidang itu. Ini akan sulit dilakukan di mana jumlah baris kode lebih dari 1000. Dalam situasi seperti itu kita dapat menggunakan Property
dan dapat mengatur mode debug di dalam Property
.
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
Sebuah lapangan adalah variabel yang dideklarasikan secara langsung di kelas atau struct. Kelas atau struct mungkin memiliki bidang contoh atau bidang statis atau keduanya. Secara umum, Anda harus menggunakan bidang hanya untuk variabel yang memiliki aksesibilitas pribadi atau terlindungi . Data yang diekspos kelas Anda ke kode klien harus disediakan melalui metode, properti, dan pengindeks. Dengan menggunakan konstruksi ini untuk akses tidak langsung ke bidang internal, Anda dapat melindungi terhadap nilai input yang tidak valid.
Sebuah properti adalah anggota yang menyediakan mekanisme fleksibel untuk membaca, menulis, atau menghitung nilai dari bidang swasta. Properti dapat digunakan seolah-olah mereka adalah anggota data publik, tetapi mereka sebenarnya adalah metode khusus yang disebut accessors . Ini memungkinkan data diakses dengan mudah dan masih membantu meningkatkan keamanan dan fleksibilitas metode . Properti memungkinkan kelas untuk mengekspos cara publik mendapatkan dan menetapkan nilai, sambil menyembunyikan kode implementasi atau verifikasi. Accessor properti get digunakan untuk mengembalikan nilai properti, dan set accessor digunakan untuk menetapkan nilai baru.
Properti memiliki keunggulan utama yaitu memungkinkan Anda mengubah cara data pada suatu objek diakses tanpa memutus antarmuka publiknya. Misalnya, jika Anda perlu menambahkan validasi tambahan, atau mengubah bidang yang disimpan menjadi yang dihitung, Anda dapat melakukannya dengan mudah jika awalnya membuka bidang tersebut sebagai properti. Jika Anda baru saja mengekspos bidang secara langsung, maka Anda harus mengubah antarmuka publik kelas Anda untuk menambahkan fungsionalitas baru. Perubahan itu akan memecah klien yang sudah ada, mengharuskan mereka untuk dikompilasi ulang sebelum mereka dapat menggunakan versi baru dari kode Anda.
Jika Anda menulis perpustakaan kelas yang dirancang untuk konsumsi luas (seperti .NET Framework, yang digunakan oleh jutaan orang), itu bisa menjadi masalah. Namun, jika Anda menulis kelas yang digunakan secara internal di dalam basis kode kecil (katakanlah <= 50 K baris), itu benar-benar bukan masalah besar, karena tidak ada yang akan terpengaruh oleh perubahan Anda. Dalam hal ini benar-benar hanya karena preferensi pribadi.
Properti mendukung akses asimetris, yaitu Anda dapat memiliki pengambil dan penyetel atau hanya salah satu dari keduanya. Demikian pula properti mendukung aksesibilitas individu untuk pengambil / penyetel. Bidang selalu simetris, yaitu Anda selalu bisa mendapatkan dan mengatur nilainya. Pengecualian untuk ini adalah bidang hanya baca yang jelas tidak dapat diatur setelah inisialisasi.
Properti dapat berjalan untuk waktu yang sangat lama, memiliki efek samping, dan bahkan dapat melempar pengecualian. Fields cepat, tanpa efek samping, dan tidak akan pernah memberikan pengecualian. Karena efek samping, properti dapat mengembalikan nilai yang berbeda untuk setiap panggilan (seperti halnya DateTime. Sekarang, yaitu DateTime. Sekarang tidak selalu sama dengan DateTime.Now). Fields selalu mengembalikan nilai yang sama.
Fields dapat digunakan untuk parameter out / ref, properti mungkin tidak. Properti mendukung logika tambahan - ini dapat digunakan untuk mengimplementasikan pemuatan malas antara lain.
Properti mendukung tingkat abstraksi dengan merangkum apa pun artinya untuk mendapatkan / mengatur nilai.
Gunakan properti di sebagian besar / semua kasus, tetapi cobalah untuk menghindari efek samping.
Di latar belakang properti dikompilasi ke dalam metode. Jadi Name
properti dikompilasi menjadi get_Name()
dan set_Name(string value)
. Anda dapat melihat ini jika mempelajari kode yang dikompilasi. Jadi ada overhead kinerja yang sangat kecil saat menggunakannya. Biasanya Anda akan selalu menggunakan Properti jika Anda mengekspos bidang ke luar, dan Anda akan sering menggunakannya secara internal jika Anda perlu melakukan validasi nilai.
Ketika Anda ingin variabel pribadi Anda (bidang) dapat diakses ke objek kelas Anda dari kelas lain, Anda perlu membuat properti untuk variabel-variabel itu.
misalnya jika saya memiliki variabel bernama "id" dan "nama" yang bersifat pribadi tetapi mungkin ada situasi di mana variabel ini diperlukan untuk operasi baca / tulis di luar kelas. Pada situasi itu, properti dapat membantu saya membuat variabel itu untuk dibaca / ditulis tergantung pada dapatkan / set yang ditentukan untuk properti. Properti dapat berupa readonly / writeonly / readwrite keduanya.
ini dia demo
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
Pertanyaan kedua di sini, "kapan seharusnya sebuah bidang digunakan alih-alih properti?", Hanya disinggung secara singkat dalam jawaban lain ini dan agak yang ini juga , tetapi tidak terlalu detail.
Secara umum, semua jawaban lain tepat tentang desain yang baik: lebih suka mengekspos properti daripada bidang yang terbuka. Meskipun Anda mungkin tidak akan secara teratur menemukan diri Anda berkata "wow, bayangkan betapa jauh lebih buruknya hal ini jika saya menjadikan ini bidang alih-alih sebuah properti", itu sangat jauh lebih jarang untuk memikirkan situasi di mana Anda akan berkata "wow, Alhamdulillah saya menggunakan bidang di sini alih-alih properti. "
Tapi ada satu keuntungan yang dimiliki bidang dibandingkan properti, dan itulah kemampuan mereka untuk digunakan sebagai parameter "ref" / "out". Misalkan Anda memiliki metode dengan tanda tangan berikut:
public void TransformPoint(ref double x, ref double y);
dan misalkan Anda ingin menggunakan metode itu untuk mengubah array yang dibuat seperti ini:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Inilah saya pikir cara tercepat untuk melakukannya, karena X dan Y adalah properti:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
Dan itu akan sangat bagus! Kecuali Anda memiliki pengukuran yang membuktikan sebaliknya, tidak ada alasan untuk melemparkan bau. Tapi saya percaya itu tidak dijamin secara teknis secepat ini:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Melakukan beberapa pengukuran sendiri, versi dengan bidang memakan waktu 61% dari waktu sebagai versi dengan properti (.NET 4.6, Windows 7, x64, mode rilis, tidak ada debugger terpasang). Semakin mahal TransformPoint
metodenya, semakin jelas perbedaannya. Untuk mengulanginya sendiri, jalankan dengan baris pertama yang dikomentari dan dengan itu tidak dikomentari.
Bahkan jika tidak ada manfaat kinerja untuk hal di atas, ada tempat-tempat lain di mana bisa menggunakan parameter ref dan out mungkin bermanfaat, seperti ketika memanggil keluarga metode Interlocked atau Volatile . Catatan: Jika ini baru bagi Anda, Volatile pada dasarnya adalah cara untuk mendapatkan perilaku yang sama dengan yang diberikan oleh volatile
kata kunci. Dengan demikian, seperti volatile
, itu tidak secara ajaib menyelesaikan semua masalah keselamatan-thread seperti namanya menunjukkan bahwa itu mungkin.
Saya jelas tidak ingin terlihat seperti saya menganjurkan Anda pergi "oh, saya harus mulai mengekspos bidang bukan properti." Intinya adalah bahwa jika Anda perlu secara teratur menggunakan anggota ini dalam panggilan yang menggunakan parameter "ref" atau "out", terutama pada sesuatu yang mungkin merupakan tipe nilai sederhana yang tidak mungkin membutuhkan elemen properti bernilai tambah lainnya, argumen bisa dibuat.
Meskipun bidang dan properti terlihat mirip satu sama lain, keduanya adalah elemen bahasa yang sangat berbeda.
Fields adalah satu-satunya mekanisme bagaimana menyimpan data di tingkat kelas. Bidang adalah variabel konseptual pada ruang lingkup kelas. Jika Anda ingin menyimpan beberapa data ke instance kelas Anda (objek) Anda perlu menggunakan bidang. Tidak ada pilihan lain. Properti tidak dapat menyimpan data apa pun meskipun, mungkin terlihat mereka mampu melakukannya. Lihat dibawah.
Properti di sisi lain tidak pernah menyimpan data. Mereka hanya pasangan metode (dapatkan dan atur) yang secara sintaksis dapat dipanggil dengan cara yang mirip dengan bidang dan dalam kebanyakan kasus mereka mengakses bidang (untuk membaca atau menulis), yang merupakan sumber dari beberapa kebingungan. Tetapi karena metode properti adalah (dengan beberapa batasan seperti prototipe tetap) metode C # biasa mereka dapat melakukan apa pun yang dapat dilakukan metode biasa. Ini berarti mereka dapat memiliki 1000 baris kode, mereka dapat membuang pengecualian, memanggil metode lain, bahkan virtual, abstrak atau diganti. Apa yang membuat properti spesial, adalah fakta bahwa kompiler C # menyimpan beberapa metadata tambahan ke dalam rakitan yang dapat digunakan untuk mencari properti tertentu - fitur yang banyak digunakan.
Dapatkan dan atur metode properti memiliki prototipe berikut.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
Jadi itu berarti bahwa properti dapat 'ditiru' dengan mendefinisikan bidang dan 2 metode yang sesuai.
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
Emulasi properti semacam itu tipikal untuk bahasa pemrograman yang tidak mendukung properti - seperti standar C ++. Di C # di sana Anda harus selalu memilih properti sebagai cara mengakses ke bidang Anda.
Karena hanya bidang yang dapat menyimpan data, itu berarti bahwa lebih banyak bidang kelas berisi, lebih banyak objek memori kelas tersebut akan mengkonsumsi. Di sisi lain, menambahkan properti baru ke dalam kelas tidak membuat objek dari kelas tersebut menjadi lebih besar. Inilah contohnya.
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
Meskipun metode properti dapat melakukan apa saja, dalam banyak kasus mereka berfungsi sebagai cara bagaimana mengakses bidang objek. Jika Anda ingin membuat bidang dapat diakses oleh kelas lain, Anda dapat melakukannya dengan 2 cara.
Ini adalah kelas yang menggunakan bidang publik.
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
Meskipun kode ini benar-benar valid, dari sudut pandang desain, ia memiliki beberapa kelemahan. Karena bidang dapat dibaca dan ditulis, Anda tidak dapat mencegah pengguna menulis ke bidang. Anda dapat menerapkan readonly
kata kunci, tetapi dengan cara ini, Anda harus menginisialisasi bidang hanya baca dalam konstruktor. Terlebih lagi, tidak ada yang mencegah Anda untuk menyimpan nilai yang tidak valid ke dalam bidang Anda.
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
Kode ini valid, semua tugas akan dieksekusi meskipun tidak logis. Age
memiliki nilai negatif, YearOfBirth
jauh di masa depan dan tidak sesuai dengan Usia dan FullName
nol. Dengan bidang Anda tidak dapat mencegah penggunaclass Name
melakukan kesalahan seperti itu.
Berikut ini adalah kode dengan properti yang memperbaiki masalah ini.
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
Versi kelas yang diperbarui memiliki keunggulan berikut.
FullName
dan YearOfBirth
diperiksa untuk nilai yang tidak valid.Age
tidak bisa ditulis. Itu berasal dariYearOfBirth
dan tahun ini.FullNameInUppercase
dikonversi FullName
menjadi KASUS UPPER. Ini adalah contoh penggunaan properti yang sedikit dibuat-buat, di mana properti biasanya digunakan untuk menyajikan nilai bidang dalam format yang lebih sesuai untuk pengguna - misalnya menggunakan lokal saat ini pada DateTime
format angka tertentu .Selain itu, properti dapat didefinisikan sebagai virtual atau diganti - hanya karena mereka adalah metode .NET biasa. Aturan yang sama berlaku untuk metode properti seperti untuk metode reguler.
C # juga mendukung pengindeks yang merupakan properti yang memiliki parameter indeks dalam metode properti. Inilah contohnya.
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
Karena C # 3.0 memungkinkan Anda untuk menentukan properti otomatis. Inilah contohnya.
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
Meskipun class AutoProps
hanya berisi properti (atau sepertinya), ia dapat menyimpan 2 nilai dan ukuran objek dari kelas ini sama dengan sizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 byte.
Alasannya sederhana. Ketika Anda mendefinisikan properti otomatis, kompiler C # menghasilkan kode otomatis yang berisi bidang tersembunyi dan properti dengan metode properti yang mengakses bidang tersembunyi ini. Berikut adalah kode yang dihasilkan oleh kompiler.
Berikut adalah kode yang dihasilkan oleh ILSpy dari rakitan yang dikompilasi. Kelas berisi bidang dan properti tersembunyi yang dihasilkan.
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}
Jadi, seperti yang Anda lihat, kompiler masih menggunakan bidang untuk menyimpan nilai - karena bidang adalah satu-satunya cara bagaimana menyimpan nilai ke objek.
Jadi seperti yang Anda lihat, meskipun properti dan bidang memiliki sintaks penggunaan yang serupa, mereka adalah konsep yang sangat berbeda.Bahkan jika Anda menggunakan properti atau peristiwa otomatis - bidang tersembunyi dihasilkan oleh kompiler tempat data nyata disimpan.
Jika Anda perlu membuat nilai bidang dapat diakses oleh dunia luar (pengguna kelas Anda) jangan gunakan bidang publik atau yang dilindungi. Bidang harus selalu ditandai sebagai pribadi. Properti memungkinkan Anda melakukan pengecekan nilai, pemformatan, konversi, dll. Dan umumnya membuat kode Anda lebih aman, lebih mudah dibaca, dan lebih dapat dikembangkan untuk modifikasi di masa mendatang.
Jika Anda akan menggunakan primitif utas, Anda terpaksa menggunakan bidang. Properti dapat merusak kode berulir Anda. Terlepas dari itu, apa yang dikatakan cory benar.
(Ini benar-benar harus menjadi komentar, tetapi saya tidak dapat memposting komentar, jadi mohon maaf jika tidak pantas sebagai posting).
Saya pernah bekerja di tempat di mana praktik yang disarankan adalah menggunakan bidang publik alih-alih properti ketika def properti yang setara hanya akan mengakses bidang, seperti pada:
get { return _afield; }
set { _afield = value; }
Alasan mereka adalah bahwa bidang publik dapat dikonversi menjadi properti di kemudian hari jika diperlukan. Rasanya agak aneh bagi saya pada saat itu. Dilihat oleh posting ini, sepertinya tidak banyak di sini akan setuju juga. Apa yang mungkin Anda katakan untuk mencoba mengubah sesuatu?
Sunting: Saya harus menambahkan bahwa semua basis kode di tempat ini dikompilasi pada saat yang sama, sehingga mereka mungkin berpikir bahwa mengubah antarmuka publik kelas (dengan mengubah bidang publik ke properti) tidak menjadi masalah.
Secara teknis, saya tidak berpikir ada perbedaan, karena properti hanya pembungkus bidang yang dibuat oleh pengguna atau secara otomatis dibuat oleh kompiler. Tujuan properti adalah untuk menegakkan enkapsulasi dan untuk menawarkan fitur seperti metode yang ringan. Ini hanya praktik yang buruk untuk menyatakan bidang sebagai publik, tetapi tidak memiliki masalah.
Fields adalah variabel anggota biasa atau instance anggota kelas. Properti adalah abstraksi untuk mendapatkan dan mengatur nilainya . Properti juga disebut accessors karena mereka menawarkan cara untuk mengubah dan mengambil bidang jika Anda mengekspos bidang di kelas sebagai pribadi. Secara umum, Anda harus mendeklarasikan variabel anggota Anda pribadi, lalu mendeklarasikan atau mendefinisikan properti untuk mereka.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
Properti merangkum bidang, sehingga memungkinkan Anda untuk melakukan pemrosesan tambahan pada nilai yang akan ditetapkan atau diambil. Biasanya diperlukan terlalu banyak untuk menggunakan properti jika Anda tidak akan melakukan pra atau pasca pengolahan pada nilai bidang.
IMO, Properties hanyalah pasangan fungsi / metode / antarmuka "SetXXX ()" "GetXXX ()" yang kami gunakan sebelumnya, tetapi mereka lebih ringkas dan elegan.
Bidang pribadi tradisional ditetapkan melalui metode pengambil dan penyetel. Demi mengurangi kode, Anda dapat menggunakan properti untuk mengatur bidang sebagai gantinya.
ketika Anda memiliki kelas yang "Mobil". Properti adalah warna, bentuk ..
Sedangkan field adalah variabel yang didefinisikan dalam ruang lingkup kelas.
Dari Wikipedia - pemrograman berorientasi objek :
Object-oriented programming (OOP) adalah paradigma pemrograman yang didasarkan pada konsep "objek", yang merupakan struktur data yang berisi data, dalam bentuk bidang , sering dikenal sebagai atribut; dan kode, dalam bentuk prosedur, sering dikenal sebagai metode . (penekanan ditambahkan)
Properti sebenarnya adalah bagian dari perilaku objek, tetapi dirancang untuk memberikan konsumen objek ilusi / abstraksi bekerja dengan data objek.
Desain saya dari sebuah field adalah bahwa field perlu dimodifikasi hanya oleh orang tuanya, maka dari itu kelas. Hasilnya variabel menjadi pribadi, maka untuk dapat memberikan hak untuk membaca kelas / metode di luar saya pergi melalui sistem properti hanya dengan Dapatkan. Bidang ini kemudian diambil oleh properti dan hanya-baca! Jika Anda ingin memodifikasinya, Anda harus melalui metode (misalnya konstruktor) dan saya menemukan bahwa berkat cara ini membuat Anda aman, kami memiliki kontrol yang lebih baik atas kode kami karena kami "mengarah". Satu bisa sangat baik selalu meletakkan semuanya di depan umum sehingga setiap kasus yang mungkin, gagasan variabel / metode / kelas dll ... menurut saya hanyalah bantuan untuk pengembangan, pemeliharaan kode. Misalnya, jika seseorang melanjutkan kode dengan bidang publik, ia dapat melakukan apa saja dan karenanya hal-hal "tidak logis" dalam kaitannya dengan tujuan, logika mengapa kode itu ditulis. Ini sudut pandang saya.
Ketika saya menggunakan model privat bidang publik / publik hanya baca, untuk 10 bidang privat saya harus menulis 10 properti publik! Kode bisa sangat besar lebih cepat. Saya menemukan setter pribadi dan sekarang saya hanya menggunakan properti publik dengan setter pribadi. Setter di latar belakang membuat bidang pribadi.
Itu sebabnya gaya pemrograman klasik lama saya adalah:
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
Gaya pemrograman baru saya:
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
Pikirkan tentang hal ini: Anda memiliki kamar dan pintu untuk memasuki ruangan ini. Jika Anda ingin memeriksa bagaimana siapa yang masuk dan mengamankan kamar Anda, maka Anda harus menggunakan properti jika tidak mereka tidak akan ada pintu dan setiap orang dengan mudah masuk tanpa peraturan apa pun
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
Orang-orang masuk ke sectionOne dengan mudah, tidak ada pengecekan
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
Sekarang Anda memeriksa orang itu dan tahu apakah ia memiliki sesuatu yang jahat dengannya
Fields adalah variabel dalam kelas. Fields adalah data yang dapat Anda enkapsulasi melalui penggunaan pengubah akses.
Properties mirip dengan Fields dalam mendefinisikan status dan data yang terkait dengan objek.
Tidak seperti bidang properti memiliki sintaks khusus yang mengontrol bagaimana seseorang membaca data dan menulis data, ini dikenal sebagai operator get and set. Himpunan logika sering dapat digunakan untuk melakukan validasi.
Properti adalah jenis khusus anggota kelas, Di properti kami menggunakan metode Set atau Get yang telah ditentukan. Mereka menggunakan pengakses yang dapat digunakan untuk membaca, menulis, atau mengubah nilai bidang pribadi.
Sebagai contoh, mari kita ambil kelas bernama Employee
, dengan bidang pribadi untuk nama, umur, dan Employee_Id. Kami tidak dapat mengakses bidang ini dari luar kelas, tetapi kami dapat mengakses bidang pribadi ini melalui properti.
Mengapa kita menggunakan properti?
Membuat bidang kelas menjadi publik & mengeksposnya berisiko, karena Anda tidak akan memiliki kendali atas apa yang ditugaskan & dikembalikan.
Untuk memahami ini dengan jelas dengan sebuah contoh, mari kita ambil kelas siswa yang memiliki ID, passmark, nama. Sekarang dalam contoh ini beberapa masalah dengan bidang publik
Untuk menghapus masalah ini, kami menggunakan metode Get and set.
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
Sekarang kita ambil contoh metode get and set
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
Info tambahan: Secara default, dapatkan dan atur aksesor dapat diakses seperti properti itu sendiri. Anda dapat mengontrol / membatasi aksesor atau aksesibilitas secara individual (untuk mendapatkan dan mengatur) dengan menerapkan pengubah akses yang lebih ketat pada mereka.
Contoh:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Sini dapatkan masih diakses secara publik (karena properti adalah publik), tetapi set dilindungi (penentu akses yang lebih terbatas).
Properti digunakan untuk mengekspos bidang. Mereka menggunakan pengakses (set, dapatkan) di mana nilai-nilai bidang pribadi dapat dibaca, ditulis atau dimanipulasi.
Properti tidak memberi nama lokasi penyimpanan. Sebaliknya, mereka memiliki pengakses yang membaca, menulis, atau menghitung nilai-nilai mereka.
Dengan menggunakan properti, kita dapat menetapkan validasi pada tipe data yang ditetapkan pada bidang.
Sebagai contoh, kami memiliki usia bidang bilangan bulat pribadi yang harus kami beri nilai positif karena usia tidak boleh negatif.
Kita bisa melakukan ini dengan dua cara menggunakan pengambil dan setter dan menggunakan properti.
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
Properti yang Diimplementasikan Otomatis jika kita tidak logika dalam mendapatkan dan mengatur aksesor kita dapat menggunakan properti yang diimplementasikan otomatis.
Saat kompilasi properti yang diimplementasikan secara otomatis membuat bidang pribadi dan anonim yang hanya dapat diakses melalui get dan set accessors.
public int Age{get;set;}
Properties Abstrak Kelas abstrak mungkin memiliki properti abstrak, yang harus diimplementasikan di kelas turunan
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Kami dapat secara pribadi mengatur properti. Dalam hal ini kami dapat secara pribadi mengatur properti otomatis (diatur dengan di kelas)
public int MyProperty
{
get; private set;
}
Anda dapat mencapai hal yang sama dengan kode ini. Dalam properti ini set fitur tidak tersedia karena kami harus menetapkan nilai ke bidang secara langsung.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
Sebagian besar kasus itu akan menjadi nama properti yang Anda akses sebagai lawan dari nama variabel ( bidang ) Alasan untuk itu adalah dianggap praktik yang baik dalam. NET dan di C # khususnya untuk melindungi setiap bagian data dalam kelas , apakah itu variabel instan atau variabel statis (variabel kelas) karena dikaitkan dengan kelas.
Lindungi semua variabel tersebut dengan properti terkait yang memungkinkan Anda untuk menentukan, mengatur , dan mendapatkan pengakses dan melakukan hal-hal seperti validasi ketika Anda memanipulasi bagian-bagian data tersebut.
Tetapi dalam kasus lain seperti kelas Math (System namespace), ada beberapa properti statis yang dibangun ke dalam kelas. salah satunya adalah matematika konstan PI
misalnya. Math.PI
dan karena PI adalah sepotong data yang terdefinisi dengan baik, kita tidak perlu memiliki banyak salinan PI, itu akan selalu bernilai sama. Jadi variabel statis kadang-kadang digunakan untuk berbagi data di antara objek kelas, tetapi variabel juga biasa digunakan untuk informasi konstan di mana Anda hanya perlu satu salinan sepotong data.