Pertanyaan Apa perbedaan antara bidang dan properti?


Dalam C #, apa yang membuat bidang berbeda dari properti, dan kapan seharusnya suatu bidang digunakan sebagai ganti properti?


826


asal


Jawaban:


Properti mengekspos bidang. Bidang harus (hampir selalu) dijaga pribadi untuk kelas dan diakses melalui mendapatkan dan mengatur properti. Properti menyediakan tingkat abstraksi yang memungkinkan Anda mengubah bidang sementara tidak memengaruhi 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 mengenkapsulasi bidang, mereka bisa melakukan perhitungan pada bidang lain, atau melayani tujuan lain.

@GSS menunjukkan bahwa Anda juga dapat melakukan logika lain, seperti validasi, ketika sebuah properti diakses, fitur lain yang bermanfaat.


741



Prinsip-prinsip pemrograman berorientasi objek mengatakan bahwa, kerja internal kelas harus disembunyikan dari dunia luar. Jika Anda mengekspos bidang Anda pada intinya mengekspos implementasi internal kelas. Oleh karena itu kami membungkus bidang dengan Properties (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
}

207



Perbedaan penting adalah antarmuka dapat memiliki properti tetapi bukan bidang. Ini, bagi saya, menggarisbawahi bahwa properti harus digunakan untuk mendefinisikan antarmuka publik kelas sementara bidang dimaksudkan untuk digunakan dalam pekerjaan internal pribadi kelas. Sebagai aturan saya jarang membuat bidang publik dan sama saya jarang membuat properti non-publik.


126



Saya akan memberi Anda beberapa contoh penggunaan properti yang mungkin membuat roda gigi berputar:

  • Inisialisasi Malas: Jika Anda memiliki properti objek yang mahal untuk dimuat, tetapi tidak diakses sebanyak itu dalam menjalankan kode yang normal, Anda dapat menunda pemuatannya melalui properti. Dengan cara itu, itu hanya duduk di sana, tetapi pertama kalinya modul lain mencoba untuk memanggil properti itu, ia akan memeriksa apakah bidang yang mendasari adalah null - jika itu, ia berjalan di depan dan memuatnya, tidak dikenal ke modul panggilan. Ini dapat sangat mempercepat inisialisasi objek.
  • Pelacakan Kotor: Yang sebenarnya saya pelajari dari saya pertanyaan sendiri di sini di StackOverflow. Ketika saya memiliki banyak objek yang nilai-nilai mungkin telah berubah selama menjalankan, saya dapat menggunakan properti untuk melacak jika mereka perlu disimpan kembali ke database atau tidak. Jika tidak satu pun properti dari suatu objek telah berubah, bendera IsDirty tidak akan tersandung, dan oleh karena itu fungsi penyimpanan akan melewatinya ketika memutuskan apa yang perlu kembali ke database.

85



Menggunakan Properties, Anda bisa melempar acara, ketika nilai properti diubah (alias. PropertyChangedEvent) atau sebelum nilai diubah untuk mendukung pembatalan.

Ini tidak mungkin 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(){
   EventHandler localEvent = NameChanging;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }

 private void OnNameChanged(){
   EventHandler localEvent = NameChanged;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }
}

43



Karena banyak dari mereka telah menjelaskan dengan pro dan kontra teknis Properties dan Field, saatnya untuk masuk ke contoh waktu nyata.

1. Properti memungkinkan Anda mengatur tingkat akses hanya-baca

Pertimbangkan kasusnya dataTable.Rows.Count dan dataTable.Columns[i].Caption. Mereka berasal dari kelas DataTable dan keduanya bersifat publik kepada kami. Perbedaan dalam tingkat akses kepada mereka adalah bahwa kita tidak dapat menetapkan nilai dataTable.Rows.Count tapi kita bisa baca dan tulis dataTable.Columns[i].Caption. Apakah itu mungkin melalui Field? Tidak!!! Ini bisa dilakukan dengan Properties hanya.

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 telah bekerja dengan Button di Visual Studio. Sifat-sifatnya ditampilkan dalam PropertyGrid seperti Text,Name dll. Ketika kita drag dan drop tombol, dan ketika kita mengklik properti, secara otomatis akan menemukan kelas Button dan filter Properties dan tunjukkan itu di PropertyGrid (dimana PropertyGrid tidak akan ditampilkan Field meskipun mereka bersifat 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, sifat-sifatnya Name dan Text akan ditampilkan, tetapi tidak SomeProperty. Mengapa??? Karena Properti dapat menerima Atribut. Itu tidak muncul dalam kasus di mana [Browsable(false)] salah.

3. Dapat mengeksekusi 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 Properties yang dapat digunakan dalam Binding Source

Sumber Binding membantu kami untuk mengurangi jumlah baris kode. Fields tidak diterima oleh BindingSource. Kami harus menggunakan Properties untuk itu.

5. Mode debug

Pertimbangkan kami gunakan Field untuk memegang nilai. Pada titik tertentu kita perlu melakukan debug dan memeriksa di mana nilainya 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 dalamnya Property.

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }

36



PERBEDAAN - PENGGUNAAN (kapan dan mengapa)

SEBUAH bidang adalah variabel yang dideklarasikan langsung di kelas atau struct. Kelas atau struct mungkin memiliki bidang contoh atau bidang statis atau keduanya. Umumnya, Anda harus menggunakan bidang hanya untuk variabel yang memiliki aksesibilitas pribadi atau dilindungi. Data yang ditunjukkan 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 menjaga terhadap nilai input yang tidak valid.

SEBUAH milik adalah anggota yang menyediakan mekanisme fleksibel untuk membaca, menulis, atau menghitung nilai bidang pribadi. Properti dapat digunakan seolah-olah mereka adalah anggota data publik, tetapi mereka sebenarnya adalah metode khusus yang disebut akseptor. Ini memungkinkan data diakses dengan mudah dan tetap membantu mempromosikan keamanan dan fleksibilitas metode. Properti memungkinkan kelas untuk mengekspos cara umum mendapatkan dan menetapkan nilai, sambil menyembunyikan implementasi atau kode verifikasi. A mendapatkan accessor properti digunakan untuk mengembalikan nilai properti, dan satu set accessor digunakan untuk menetapkan nilai baru.


21



Properti memiliki keuntungan utama yang memungkinkan Anda untuk mengubah cara data pada objek diakses tanpa melanggar antarmuka publiknya. Misalnya, jika Anda perlu menambahkan validasi tambahan, atau mengubah bidang yang tersimpan menjadi terhitung, Anda dapat melakukannya dengan mudah jika awalnya Anda memaparkan bidang sebagai properti. Jika Anda hanya mengekspos bidang secara langsung, maka Anda harus mengubah antarmuka publik kelas Anda untuk menambahkan fungsi baru. Perubahan itu akan mematahkan klien yang ada, yang mengharuskan mereka dikompilasi ulang sebelum mereka dapat menggunakan versi baru 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 baris K), itu benar-benar bukan masalah besar, karena tidak akan ada yang dirugikan oleh perubahan Anda. Dalam hal ini benar-benar hanya turun ke preferensi pribadi.


9