Dalam C #, apa perbedaan antara publik, pribadi, dilindungi, dan tidak memiliki pengubah akses?

728

Semua tahun kuliah saya, saya memiliki telah menggunakan public, dan ingin tahu perbedaan antara public, privatedan protected?

Juga apa yang staticdilakukan sebagai lawan tidak memiliki apa-apa?

Tuan
sumber

Jawaban:

1008

Akses pengubah

Dari docs.microsoft.com :

public

Jenis atau anggota dapat diakses oleh kode lain dalam rakitan yang sama atau rakitan lain yang merujuknya.

private

Jenis atau anggota hanya dapat diakses oleh kode di kelas atau struct yang sama.

protected

Tipe atau anggota hanya dapat diakses oleh kode di kelas atau struct yang sama, atau dalam kelas turunan.

private protected (ditambahkan dalam C # 7.2)

Tipe atau anggota hanya dapat diakses oleh kode di kelas atau struct yang sama, atau dalam kelas turunan dari rakitan yang sama, tetapi tidak dari rakitan lain.

internal

Jenis atau anggota dapat diakses oleh kode apa pun di rakitan yang sama, tetapi tidak dari rakitan lain.

protected internal

Jenis atau anggota dapat diakses dengan kode apa pun di rakitan yang sama, atau oleh kelas turunan di rakitan lain.

Ketika tidak ada pengubah akses yang ditetapkan, pengubah akses standar digunakan. Jadi selalu ada beberapa bentuk pengubah akses bahkan jika itu tidak diatur.

static pengubah

Pengubah statis pada kelas berarti bahwa kelas tidak dapat dipakai, dan bahwa semua anggotanya statis. Anggota statis memiliki satu versi terlepas dari berapa banyak instance dari tipe penutupnya dibuat.

Kelas statis pada dasarnya sama dengan kelas non-statis, tetapi ada satu perbedaan: kelas statis tidak dapat dipakai secara eksternal. Dengan kata lain, Anda tidak dapat menggunakan kata kunci baru untuk membuat variabel dari tipe kelas. Karena tidak ada variabel instan, Anda mengakses anggota kelas statis dengan menggunakan nama kelas itu sendiri.

Namun, ada yang namanya konstruktor statis . Setiap kelas dapat memiliki salah satunya, termasuk kelas statis. Mereka tidak dapat dipanggil secara langsung & tidak dapat memiliki parameter (selain parameter tipe apa pun di kelas itu sendiri). Konstruktor statis dipanggil secara otomatis untuk menginisialisasi kelas sebelum instance pertama dibuat atau anggota statis dirujuk. Terlihat seperti ini:

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }

    public static string Bar { get; set; }
}

Kelas statis sering digunakan sebagai layanan, Anda dapat menggunakannya seperti:

MyStaticClass.ServiceMethod(...);
mbillard
sumber
17
Dan Anda dapat memiliki metode statis di kelas non-statis, bukan?
John Bubriski
14
Ya, mereka akan berperilaku sama seperti pada contoh saya.
mbillard
7
Apa arti istilah "majelis" dalam konteks ini?
Jonathan Gleason
1
@gotoVoid Apa pun yang Anda cari di Google salah. Menurut MSDN , internal yang dilindungi berarti bahwa, "tipe atau anggota dapat diakses dengan kode apa pun dalam majelis yang dideklarasikan, atau dari dalam kelas turunan di majelis lain."
Kevin
2
Apa perbedaan antara Protected dan Private Protected? Bagi saya, kedengarannya sama saja ..
goofyui
161

Gambaran umum grafis (ringkasan singkatnya)

Visibilitas

Karena kelas statis disegel, mereka tidak dapat diwarisi (kecuali dari Objek), sehingga kata kunci yang diproteksi tidak valid pada kelas statis.



Untuk default jika Anda tidak menempatkan pengubah akses di depan, lihat di sini:
Visibilitas default untuk kelas dan anggota C # (bidang, metode, dll.)?

Tidak bersarang

enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

Bersarang:

nested enum      public
nested interface public
nested class     private
nested struct    private

Juga, ada kata kunci yang disegel, yang membuat kelas tidak dapat diwariskan.
Juga, di VB.NET, kata kunci terkadang berbeda, jadi di sini lembar contekan:

Setara VB vs CS

Stefan Steiger
sumber
1
@ ᴀʀᴜn BᴇrtiL: Apakah Anda yakin? Kelas turunan dalam majelis berbeda?
Stefan Steiger
kelas turunan dalam majelis yang sama kita bisa, berbeda kita tidak bisa. Kupikir maksudmu seperti di majelis yang sama ...
Arun Bertil
1
@ ᴀʀᴜn BᴇrtiL: Hmm, benar, ini sebenarnya harus ditetaskan.
Stefan Steiger
1
Saya pikir ada kesalahan dalam diagram. Jika internal digunakan untuk suatu kelas, kelas tersebut dapat diturunkan oleh kelas lain dalam rakitan yang sama. Juga jika pengubah internal digunakan pada properti, properti ini juga dapat diakses di kelas turunan dalam rakitan yang sama. Mungkin diagram itu benar karena ada "ya" di bawah "yang mengandung perakitan", tetapi bisa disalahpahami karena ada "tidak" di bawah "kelas turunan".
AH.
160

Publik - Jika Anda dapat melihat kelas, maka Anda dapat melihat metodenya

Pribadi - Jika Anda adalah bagian dari kelas, maka Anda dapat melihat metodenya, jika tidak.

Dilindungi - Sama seperti Pribadi, ditambah semua keturunan juga dapat melihat metode ini.

Statis (kelas) - Ingat perbedaan antara "Kelas" dan "Objek"? Lupakan semua itu. Mereka sama dengan "statis" ... kelas adalah satu-satunya contoh dari dirinya sendiri.

Statis (metode) - Setiap kali Anda menggunakan metode ini, ia akan memiliki kerangka acuan independen dari instance kelas yang sebenarnya.

JosephStyons
sumber
1
Tidak bisakah Anda memiliki metode statis di kelas yang tidak statis?
John Bubriski
1
Ya, tapi saya berbicara tentang kelas statis. Saya menambahkan entri terpisah untuk menjelaskan metode statis. Terima kasih atas tangkapannya.
JosephStyons
2
'Objek' mungkin bukan istilah yang baik di sini ketika berbicara tentang C #, karena tipe dasar untuk semua kelas adalah System.Object . 'Instance' akan menjadi kata yang lebih baik, atau 'objek' (huruf kecil 'O').
lesderid
@lesderid 'objek' adalah alias dari 'System.Object', menggunakannya mungkin membingungkan juga. 'instance' akan lebih baik, kurasa :)
dpp
aturan yang sama berlaku untuk struct.
gsharp
35

Reposting diagram yang luar biasa dari jawaban ini .

Berikut ini semua pengubah akses dalam diagram Venn, dari yang lebih membatasi hingga yang lebih bebas:

private:
masukkan deskripsi gambar di sini

private protected: - ditambahkan dalam C # 7.2
masukkan deskripsi gambar di sini

internal:
masukkan deskripsi gambar di sini

protected:
masukkan deskripsi gambar di sini

protected internal:
masukkan deskripsi gambar di sini

public:
masukkan deskripsi gambar di sini

Paul
sumber
24

masukkan deskripsi gambar di sini

using System;

namespace ClassLibrary1
{
    public class SameAssemblyBaseClass
    {
        public string publicVariable = "public";
        protected string protectedVariable = "protected";
        protected internal string protected_InternalVariable = "protected internal";
        internal string internalVariable = "internal";
        private string privateVariable = "private";
        public void test()
        {
            // OK
            Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(publicVariable);

            // OK
            Console.WriteLine(protectedVariable);

            // OK
            Console.WriteLine(internalVariable);

            // OK
            Console.WriteLine(protected_InternalVariable);
        }
    }

    public class SameAssemblyDerivedClass : SameAssemblyBaseClass
    {
        public void test()
        {
            SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }

    public class SameAssemblyDifferentClass
    {
        public SameAssemblyDifferentClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // NOT OK
            // Console.WriteLine(privateVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            //Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }
}

 using System;
        using ClassLibrary1;
        namespace ConsoleApplication4

{
    class DifferentAssemblyClass
    {
        public DifferentAssemblyClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            // Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protectedVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protected_InternalVariable);
        }
    }

    class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
    {
        static void Main(string[] args)
        {
            DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            //Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);

            SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
            dd.test();
        }
    }
}
Narottam Goyal
sumber
1
Saya tidak melihat apa yang ditambahkan jawaban ini atas banyak jawaban lain dari lima tahun terakhir.
John Saunders
4
Ini hanya penjelasan sederhana. Karena jawaban lain agak membingungkan dan setengahnya dijawab :)
Narottam Goyal
4
@ John Saunders: Membedakan dengan memisahkan visibilitas untuk kelas turunan antara kelas yang sama dan kelas berada di majelis yang berbeda. Ditambah lagi, dia memberikan cara dia mendapatkan informasi itu dengan menunjukkan kode sampelnya. Jadi itu sebenarnya menambah jawaban lain. Necromancing-nya mungkin dipicu oleh komentar saya dalam jawaban saya.
Stefan Steiger
2
"Turunan kelas dalam majelis berbeda" - ini menambah nilai bagan yang sudah diberikan dalam jawaban lain. Perbedaannya sangat membantu terutama dalam kasus "internal yang dilindungi"
Nirman
Saya menemukan bagan ini menjadi yang paling mudah untuk saya pahami. Untuk menjaga ini saat ini (dengan C # 7.2), untuk menambahkan Private Protected, itu akan menjadi: kelas yang sama = Yes, rakitan yang sama, kelas turunan = Yes, rakitan yang sama, setiap kelas = NO, rakitan berbeda, kelas turunan = NO, rakitan berbeda, setiap kelas = NO. Satu saran tambahan juga adalah untuk tidak mengganti urutan kata protected internal, karena hal ini memecah pneumonic dari jawaban @ user1810087
Intrastellar Explorer
22

Mengenai pertanyaan tentang Tidak Ada

  • Jenis namespace adalah internal secara default
  • Anggota tipe apa pun, termasuk tipe bertingkat bersifat pribadi secara default
leppie
sumber
15

Namun pendekatan visual lain dari pengubah akses saat ini (C # 7.2). Semoga skema ini membantu mengingatnya dengan lebih mudah
(klik gambar untuk tampilan interaktif.)

pengubah akses interaktif svg

Diluar didalam

Jika Anda kesulitan mengingat pengubah akses dua kata, ingat bagian luar .

  • dilindungi pribadi : pribadi di luar (rakitan yang sama) dilindungi di dalam (rakitan yang sama)
  • dilindungi internal : terlindungi di luar (rakitan yang sama) internal di dalam (rakitan yang sama)
pengguna1810087
sumber
11

Hmm.

Lihat di sini: Access Modifiers .

Pendeknya:

Publik memberikan metode atau jenis visibilitas lengkap dari jenis / kelas lain.

Pribadi hanya mengizinkan tipe yang berisi metode pribadi / akses variabel ke metode / variabel pribadi (perhatikan bahwa kelas bersarang juga memiliki akses ke kelas yang mengandung metode / variabel pribadi).

Dilindungi mirip dengan privat kecuali kelas turunan juga dapat mengakses metode yang dilindungi.

"Tidak ada" adalah VB.NET setara dengan nol. Meskipun jika Anda mengacu pada "tidak ada" yang berarti "tidak ada pengubah akses", maka itu tergantung, meskipun aturan praktis yang sangat kasar (tentu saja dalam C #) adalah bahwa jika Anda tidak secara eksplisit menentukan pengubah akses, metode / variabel deklarasi biasanya dibatasi . yaitu

public class MyClass
{
    string s = "";
}

secara efektif sama dengan:

public class MyClass
{
    private string s = "";
}

Artikel MSDN yang ditautkan akan menawarkan deskripsi sepenuhnya ketika tidak ada pengubah akses yang ditentukan secara eksplisit.

CraigTP
sumber
8

publik - dapat diakses oleh siapa saja di mana saja.
privat - hanya dapat diakses dari dalam kelas yang merupakan bagian darinya.
terlindung - hanya dapat diakses dari dalam kelas atau objek apa pun yang diturunkan dari kelas.

Tidak ada yang seperti null tetapi di VB.
Statis berarti Anda memiliki satu instance dari objek itu, metode untuk setiap instance dari kelas itu.

Tony
sumber
4

mmm ...

Statis berarti Anda dapat mengakses fungsi itu tanpa memiliki instance kelas.

Anda dapat mengakses langsung dari definisi kelas.

gbianchi
sumber
4

Status Privat menunjukkan bahwa variabel hanya dapat diakses oleh objek dari kelas yang sama. Status yang dilindungi memperluas akses itu untuk memasukkan keturunan kelas juga.

"dari tabel di atas kita dapat melihat perbedaan antara pribadi dan dilindungi ... saya pikir keduanya sama .... jadi apa perlunya dua perintah terpisah"

Periksa tautan MSDN untuk informasi lebih lanjut

Grant Hood
sumber
3

Pengubah akses tersebut menentukan di mana anggota Anda terlihat. Anda mungkin harus membaca ini. Ambil tautan yang diberikan oleh IainMH sebagai titik awal.

Anggota statis adalah satu per kelas dan bukan satu per instance.

jpfollenius
sumber
3

Perhatikan dengan cermat aksesibilitas kelas Anda. Kelas dan metode publik dan dilindungi secara default dapat diakses untuk semua orang.

Microsoft juga tidak terlalu jelas dalam memperlihatkan pengubah akses (publik, dilindungi, dll. Kata kunci) ketika kelas baru di Visual Studio dibuat. Jadi, berhati-hatilah dan pikirkan aksesibilitas kelas Anda karena itu adalah pintu menuju internal implementasi Anda.

Patrick Peters
sumber
2

Saya pikir itu terkait dengan desain OOP yang baik. Jika Anda adalah pengembang perpustakaan Anda ingin menyembunyikan cara kerja perpustakaan Anda. Dengan begitu, Anda bisa memodifikasi inner library Anda nantinya. Jadi Anda menempatkan metode anggota dan bantuan Anda sebagai pribadi, dan hanya metode antarmuka yang bersifat publik. Metode yang harus ditimpa harus dilindungi.

Darius Kucinskas
sumber
1

C # memiliki total 6 pengubah akses:

pribadi : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat di dalam tipe yang berisi, tidak terlihat oleh tipe turunan, tipe lain dalam rakitan yang sama atau tipe di luar rakitan yang berisi. yaitu, akses dibatasi hanya untuk tipe yang mengandung.

dilindungi : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat di dalam tipe yang berasal dari tipe yang mengandung di dalam rakitan yang berisi, dan tipe yang berasal dari tipe yang mengandung di luar rakitan yang berisi. yaitu, akses terbatas pada tipe turunan dari tipe yang mengandung.

internal : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat di dalam rakitan yang berisi anggota ini, tidak dapat dilihat oleh rakitan di luar rakitan yang berisi. yaitu, akses dibatasi hanya untuk memuat perakitan.

dilindungi internal : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat di dalam tipe-tipe yang berasal dari tipe yang mengandung di dalam atau di luar rakitan yang berisi, itu juga terlihat oleh semua tipe di dalam rakitan yang berisi. yaitu, akses dibatasi untuk memuat jenis perakitan atau turunan.

publik : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat di dalam majelis yang berisi anggota ini, atau majelis lain yang merujuk pada majelis yang berisi. yaitu akses tidak terbatas.

C # 7.2 menambahkan tingkat aksesibilitas baru:

dilindungi pribadi : Anggota yang dideklarasikan dengan aksesibilitas ini dapat terlihat dalam tipe yang berasal dari tipe yang mengandung ini dalam rakitan yang berisi. Itu tidak terlihat oleh tipe apa pun yang tidak berasal dari tipe yang mengandung, atau di luar rakitan yang mengandung. yaitu, akses terbatas pada tipe turunan dalam rakitan yang berisi.

Sumber termasuk kode sampel pengubah akses pribadi yang dilindungi

Baccata
sumber
0

Deskripsi semua pengubah akses untuk C #

masukkan deskripsi gambar di sini

snr
sumber