C # 'da, genel, özel, korumalı ve erişim değiştiricisine sahip olmama arasındaki fark nedir?


728

Tek sahip üniversite yıllarından kullanıyorum publicve arasındaki farkı bilmek istiyorum public, privateve protected?

Ayrıca statichiçbir şeye sahip olmanın aksine ne yapar ?

Yanıtlar:


1008

Erişim değiştiricileri

Gönderen docs.microsoft.com :

public

Tür veya üyeye aynı derlemedeki herhangi bir kod veya ona başvuran başka bir derleme tarafından erişilebilir.

private

Tür veya üyeye yalnızca aynı sınıf veya yapıdaki kodla erişilebilir.

protected

Tür veya üyeye yalnızca aynı sınıf veya yapıdaki veya türetilmiş bir sınıftaki kodla erişilebilir.

private protected (C # 7.2'ye eklenmiştir)

Tür veya üyeye yalnızca aynı sınıf veya yapıdaki veya aynı derlemeden türetilmiş bir sınıftaki kodla erişilebilir, ancak başka bir derlemeden erişilemez.

internal

Tür veya üyeye aynı montajdaki herhangi bir kodla erişilebilir, ancak başka bir montajdan erişilemez.

protected internal

Tür veya üyeye aynı montajdaki herhangi bir kod veya başka bir montajdaki herhangi bir türetilmiş sınıf tarafından erişilebilir.

Herhangi bir erişim değiştirici ayarlanmadığında, varsayılan bir erişim değiştirici kullanılır. Bu nedenle, ayarlanmamış olsa bile her zaman bir çeşit erişim değiştirici vardır.

static niteleyici

Bir sınıftaki statik değiştirici, sınıfın başlatılamadığı ve tüm üyelerinin statik olduğu anlamına gelir. Statik bir üye, çevreleme türünün kaç örneğinin oluşturulduğuna bakılmaksızın bir sürüme sahiptir.

Statik sınıf temel olarak statik olmayan bir sınıfla aynıdır, ancak bir fark vardır: statik bir sınıf harici olarak başlatılamaz. Başka bir deyişle, sınıf türünde bir değişken oluşturmak için yeni anahtar sözcüğü kullanamazsınız. Örnek değişkeni olmadığından, statik adın üyelerine sınıf adının kendisini kullanarak erişirsiniz.

Bununla birlikte, statik bir yapıcı gibi bir şey vardır . Statik sınıflar da dahil olmak üzere herhangi bir sınıf bunlardan birine sahip olabilir. Doğrudan çağrılamazlar ve parametreleri olamaz (sınıfın kendisinde herhangi bir tür parametresi dışında). İlk örnek oluşturulmadan veya statik üyelere başvurulmadan önce sınıfı başlatmak için statik bir yapıcı otomatik olarak çağrılır. Buna benzer:

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

    public static string Bar { get; set; }
}

Statik sınıflar genellikle hizmet olarak kullanılır, bunları şu şekilde kullanabilirsiniz:

MyStaticClass.ServiceMethod(...);

17
Statik olmayan sınıflarda statik yöntemlere sahip olabilirsiniz, değil mi?
John Bubriski

14
Evet, benim örneğimle aynı şekilde davranacaklardı.
mbillard

7
"Montaj" terimi bu bağlamda ne anlama geliyor?
Jonathan Gleason

1
@gotoVoid Google'da aradığınız her şey yanlış. MSDN'ye göre , korumalı dahili, "tür veya üyeye bildirildiği derlemedeki herhangi bir kodla veya başka bir derlemedeki türetilmiş bir sınıftan erişilebileceği" anlamına gelir.
Kevin

2
Korumalı ve Özel Korumalı arasındaki fark nedir? Bana göre, her ikisi de aynı geliyor ..
goofyui

161

Grafiksel bir genel bakış (özet olarak)

görünürlük

Yana statik sınıflar mühürlendi korumalı anahtar kelime statik sınıflar üzerinde geçersiz ararlar, bu nedenle (Object hariç) miras edilemez.



Önde hiçbir erişim değiştiricisi koymazsanız varsayılanlar için buraya bakın:
C # sınıfları ve üyeleri (alanlar, yöntemler vb.) İçin varsayılan görünürlük?

Sigara iç içe

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

İç içe geçmiş:

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

Ayrıca, mühürlü-anahtar kelime vardır, bu da bir sınıfı devralmaz hale getirir.
Ayrıca, VB.NET'te, anahtar kelimeler bazen farklıdır, bu yüzden burada bir hile sayfası:

VB ve CS eşdeğerleri


1
@ ᴇn BᴇrtiL: Emin misin? Farklı bir derlemede türetilmiş bir sınıf mı?
Stefan Steiger

aynı derlemede türetilmiş sınıf elde edebiliriz, farklı yapamayız.Aynı derlemede demek istediğini sanıyordum ...
Arun Bertil

1
@ ᴇn BᴇrtiL: Hmm, doğru, bu aslında taranmış olmalı.
Stefan Steiger

1
Diyagramda bir hata olduğunu düşünüyorum. İç bir sınıf için kullanılıyorsa, sınıf aynı derlemedeki başka bir sınıf tarafından türetilebilir. Ayrıca dahili değiştirici bir özellikte kullanılırsa, bu özelliğe aynı derlemedeki türetilmiş sınıfta da erişilebilir. Belki de diyagram doğrudur, çünkü "derleme içeren" altında "evet" vardır, ancak yanlış anlaşılabilir, çünkü "türetilmiş sınıflar" altında "hayır" vardır.
AH.

160

Genel - Sınıfı görebiliyorsanız, yöntemi görebilirsiniz

Özel - Sınıfın bir parçasıysanız , yöntemi görebilirsiniz, aksi halde göremezsiniz.

Korumalı - Özel ile aynı, ayrıca tüm torunlar da yöntemi görebilir.

Statik (sınıf) - "Sınıf" ve "Nesne" arasındaki farkı hatırlıyor musunuz? Hepsini unutun. "Statik" ile aynıdırlar ... sınıf kendisinin bir ve tek örneğidir.

Statik (yöntem) - Bu yöntemi her kullandığınızda, parçası olduğu sınıfın gerçek örneğinden bağımsız olarak bir referans çerçevesi olacaktır.


1
Ancak statik olmayan bir sınıfta statik yöntemleriniz olamaz mı?
John Bubriski

1
Evet, ama statik bir sınıftan bahsediyordum. Statik yöntemleri tanımlamak için ayrı bir giriş ekledim. Yakaladığınız için teşekkürler.
JosephStyons

2
Tüm nesneler için taban türü System.Object olduğundan, C # hakkında konuşurken 'Object' burada iyi bir terim olmayabilir . 'Eşgörünüm' daha iyi bir kelime veya 'nesne' (küçük harf 'O') olacaktır.
lesderid

@lesderid 'object', 'System.Object' adının bir takma adıdır, onu kullanmak da kafa karıştırıcı olabilir. '
bulut sunucusu

yapılar için de aynı kurallar geçerlidir.
gsharp

35

Bu cevaptan harika diyagramları yeniden yayınlamak .

Venn diyagramlarında daha sınırlayıcıdan daha karışık olana kadar tüm erişim değiştiricileri:

private:
resim açıklamasını buraya girin

private protected: - C # 7.2'de eklendi
resim açıklamasını buraya girin

internal:
resim açıklamasını buraya girin

protected:
resim açıklamasını buraya girin

protected internal:
resim açıklamasını buraya girin

public:
resim açıklamasını buraya girin


24

resim açıklamasını buraya girin

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();
        }
    }
}

1
Bu cevabın son beş yıldaki diğer birçok cevaba ne kattığını görmüyorum.
John Saunders

4
Bu sadece basit bir açıklama. Diğer cevaplar biraz kafa karıştırıcı ve yarısı cevap gibi :)
Narottam Goyal

4
@John Saunders: Türetilmiş bir sınıfın görünürlüğünü, aynı sınıftaki sınıfla farklı sınıftaki bir sınıf arasında ayırarak ayırt eder. Ayrıca, örnek kodunu göstererek bu bilgilere nasıl ulaştığını sunar. Yani aslında diğer cevaplara katkıda bulunuyor. Onun büyücülüğü muhtemelen cevabımdaki yorumum tarafından tetiklendi.
Stefan Steiger

2
"Farklı derlemede türetilmiş sınıf" - bu, başka bir yanıtta verilen grafiğe değer katar. Fark özellikle "korumalı iç" durumunda yararlıdır
Nirman

Bu grafiği anlaması en kolay yol olarak görüyorum. Bu akımı korumak için (C # 7.2 ile), eklemek Private Protectediçin şöyle olur: aynı sınıf = Yes, aynı montaj, türetilmiş sınıf = Yes, aynı montaj, herhangi bir sınıf = NO, farklı montaj, türetilmiş sınıf = NO, farklı montaj, herhangi bir sınıf = NO. Ek bir öneri de kelime sırasını değiştirmek değilprotected internal , @ user1810087'nin cevabından pnömoniyi bozduğu
Intrastellar Explorer

22

Hiçbir Şey Sorunu Hakkında

  • Ad alanı türleri varsayılan olarak dâhildir
  • Yuvalanmış türler dahil olmak üzere tüm tür üyeleri varsayılan olarak gizlidir

15

Mevcut erişim değiştiricinin başka bir görsel yaklaşımı (C # 7.2). Umarım şema daha kolay hatırlamaya yardımcı olur
(etkileşimli görünüm için resme tıklayın.)

etkileşimli erişim değiştiricileri svg

Dışarı içeri

İki aşamalı erişim değiştiricilerini hatırlamakta zorlanıyorsanız, içten dışa unutmayın .

  • özel korumalı : özel dış (aynı montaj) korumalı (aynı montaj)
  • korumalı iç : dış korumalı (aynı montaj) (aynı montaj)

11

Hmm.

Buraya bakın: Erişim Değiştiricileri .

Kısaca:

Genel yöntem veya türe diğer türlerden / sınıflardan tam görünürlük sağlar.

Özel yalnızca özel yöntemi / değişkeni özel yönteme / değişkene içeren türe izin verir (iç içe sınıfların da içeren sınıflara özel yöntemlere / değişkenlere erişebileceğini unutmayın).

Korumalı özel, türetilmiş sınıfların korumalı yöntemlere erişebilmesi dışında benzerdir.

"Hiçbir şey" VB.NET'in null değerine eşit olduğu anlamına gelmez. Her ne kadar "erişim değiştirici yok" anlamına gelen "hiçbir şeye" atıfta bulunuyorsanız, o zaman duruma göre değişir, ancak çok kaba bir kural (kesinlikle C #'da), bir erişim değiştiricisini açıkça belirtmemeniz durumunda, yöntem / değişken beyan genellikle olabildiğince kısıtlıdır . yani

public class MyClass
{
    string s = "";
}

etkili bir şekilde aynıdır:

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

Bağlantılı MSDN makalesi, açıkça belirtilmiş erişim değiştirici olmadığında tam bir açıklama sunar.


8

herkese açık - herhangi bir yerden herkes tarafından erişilebilir.
özel - ancak bir parçası olduğu sınıfta erişilebilir.
korumalı - yalnızca sınıftaki veya sınıftan devralınan herhangi bir nesneyle erişilebilir.

Hiçbir şey boş değil ama VB'de.
Statik, o nesnenin bir örneğine, sınıfın her örneği için bir yönteme sahip olduğunuz anlamına gelir.


4

mmm ...

Statik, sınıfın bir örneğine sahip olmadan bu işleve erişebileceğiniz anlamına gelir.

Doğrudan sınıf tanımından erişebilirsiniz.


4

Özel durumu, değişkenlere yalnızca aynı sınıftaki nesneler tarafından erişilebildiğini gösterir. Korumalı durum, erişimi sınıfın torunlarını da içerecek şekilde genişletir.

"yukarıdaki tablodan özel ve korumalı arasındaki farkı görebiliriz ... ikisinin de aynı olduğunu düşünüyorum .... yani bu iki ayrı komuta ne gerek var"

Daha fazla bilgi için MSDN bağlantısını kontrol edin


3

Bu erişim değiştiricileri üyelerinizin nerede görüneceğini belirtir. Muhtemelen bunu okumalısın. IainMH tarafından verilen bağlantıyı başlangıç ​​noktası olarak kabul edin.

Statik üyeler sınıf başına birdir ve örnek başına bir değildir.


3

Sınıflarınıza erişilebilirliğinizi dikkatlice izleyin. Herkese açık ve korunan sınıflara ve yöntemlere varsayılan olarak herkes erişebilir.

Ayrıca Microsoft, Visual Studio'da yeni sınıflar oluşturulduğunda erişim değiştiricileri (genel, korumalı, vb. Anahtar sözcükler) göstermede çok fazla sorun yaşamamaktadır. Bu yüzden, dikkatli olun ve sınıfınıza erişilebilirliğinizi düşünün, çünkü bu uygulama iç mekanlarınızın kapısıdır.


2

Bence iyi OOP tasarımı ile ilgili. Bir kütüphanenin geliştiricisiyseniz, kütüphanenizin iç işleyişini gizlemek istersiniz. Böylece kütüphane iç çalışmalarınızı daha sonra değiştirebilirsiniz. Böylece üyelerinizi ve yardımcı yöntemlerinizi özel olarak koyarsınız ve yalnızca arabirim yöntemleri herkese açıktır. Üzerine yazılması gereken yöntemler korunmalıdır.


1

C # toplam 6 erişim değiştiriciye sahiptir:

private : Bu erişilebilirlikle bildirilen üye, içerme türü içinde görülebilir, türetilmiş türler, aynı derlemedeki diğer türler veya içeren derleme dışındaki türler tarafından görülemez. yani, erişim yalnızca içerme türüyle sınırlıdır.

korumalı : Bu erişilebilirlik ile bildirilen üye, muhafaza tertibatının içindeki muhafaza tipinden türetilen tipler ve ihtiva eden tertibatın dışındaki muhafaza tipinden türetilmiş tipler içinde görülebilir. yani erişim, kapsayıcı tipten türetilmiş tiplerle sınırlıdır.

internal : Bu erişilebilirlikle beyan edilen üye, bu üyeyi içeren montajın içinde görülebilir, içeren montajın dışındaki hiçbir montaj tarafından görülemez. yani erişim, yalnızca montajı içeren tertibatla sınırlıdır.

dahili korumalı : Bu erişilebilirlikle beyan edilen üye, içerilen montajın içinde veya dışında bulunan tipten türetilen tipler içinde görülebilir, ayrıca içerilen grup içindeki herhangi bir tip tarafından da görülebilir. yani erişim, montaj veya türetilmiş tipler ihtiva etmekle sınırlıdır.

public : Bu erişilebilirlikle bildirilen üye, bu üyeyi içeren derlemede veya içeren derlemeye başvuran başka bir derlemede görülebilir. yani erişim sınırlı değildir.

C # 7.2 yeni bir erişilebilirlik düzeyi ekliyor:

özel korumalı : Bu erişilebilirlikle bildirilen üye, içerdiği montaj içinde bu içeren tipten türetilen türler içinde görülebilir. Kapsayıcı tipten türetilmemiş veya kapsayıcı grubun dışından türler tarafından görülemez. yani erişim, kaplayan tertibat içindeki türetilmiş tiplerle sınırlıdır.

Yeni özel korumalı erişim değiştiricisinin örnek kodunu içeren kaynak


0

C # için tüm erişim değiştiricilerin açıklamaları

resim açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.