Em C #, qual é a diferença entre público, privado, protegido e sem modificador de acesso?

728

Todos os meus anos de faculdade que tenho vindo a utilizar public, e gostaria de saber a diferença entre public, privatee protected?

Além disso, o que staticfaz em oposição a não ter nada?

MrM
fonte

Respostas:

1008

Modificadores de acesso

Em docs.microsoft.com :

public

O tipo ou membro pode ser acessado por qualquer outro código no mesmo assembly ou outro assembly que faça referência a ele.

private

O tipo ou membro pode ser acessado apenas por código na mesma classe ou estrutura.

protected

O tipo ou membro pode ser acessado apenas por código na mesma classe ou estrutura ou em uma classe derivada.

private protected (adicionado em C # 7.2)

O tipo ou membro pode ser acessado apenas por código na mesma classe ou estrutura ou em uma classe derivada do mesmo assembly, mas não de outro assembly.

internal

O tipo ou membro pode ser acessado por qualquer código no mesmo assembly, mas não de outro assembly.

protected internal

O tipo ou membro pode ser acessado por qualquer código no mesmo assembly ou por qualquer classe derivada em outro assembly.

Quando nenhum modificador de acesso está definido, um modificador de acesso padrão é usado. Portanto, sempre há alguma forma de modificador de acesso, mesmo que não esteja definido.

static modificador

O modificador estático em uma classe significa que a classe não pode ser instanciada e que todos os seus membros são estáticos. Um membro estático possui uma versão, independentemente de quantas instâncias do seu tipo de anexo são criadas.

Uma classe estática é basicamente a mesma que uma classe não estática, mas há uma diferença: uma classe estática não pode ser instanciada externamente. Em outras palavras, você não pode usar a nova palavra-chave para criar uma variável do tipo de classe. Como não há variável de instância, você acessa os membros de uma classe estática usando o próprio nome da classe.

No entanto, existe um construtor estático . Qualquer classe pode ter uma delas, incluindo classes estáticas. Eles não podem ser chamados diretamente e não podem ter parâmetros (exceto quaisquer parâmetros de tipo na própria classe). Um construtor estático é chamado automaticamente para inicializar a classe antes da criação da primeira instância ou de referência a qualquer membro estático. Se parece com isso:

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

    public static string Bar { get; set; }
}

Classes estáticas são frequentemente usadas como serviços, você pode usá-las da seguinte maneira:

MyStaticClass.ServiceMethod(...);
mbillard
fonte
17
E você pode ter métodos estáticos em classes não estáticas, certo?
John Bubriski
14
Sim, eles se comportariam da mesma maneira que no meu exemplo.
586 mbmbardard
7
O que o termo "assembléia" significa neste contexto?
Jonathan Gleason
1
@gotoVoid O que você pesquisou no Google está incorreto. De acordo com o MSDN , interno protegido significa que "o tipo ou membro pode ser acessado por qualquer código no assembly em que é declarado ou de dentro de uma classe derivada em outro assembly".
18715 Kevin
2
Qual é a diferença entre Protected e Private Protected? Para mim, isso soa ambos são mesmo ..
goofyui
161

Uma visão geral gráfica (resumo em poucas palavras)

Visibilidade

Como as classes estáticas são seladas, elas não podem ser herdadas (exceto Object), portanto, a palavra-chave protegida é inválida nas classes estáticas.



Para os padrões, se você não colocar nenhum modificador de acesso à frente, consulte aqui:
Visibilidade padrão para classes e membros de C # (campos, métodos etc.)?

Não aninhado

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

Aninhado:

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

Além disso, existem as palavras-chave seladas, o que torna uma classe não herdável.
Além disso, no VB.NET, as palavras-chave às vezes são diferentes, então aqui está uma folha de dicas:

Equivalentes VB vs. CS

Stefan Steiger
fonte
1
@ ᴇn BᴇrtiL: Você tem certeza? Uma classe derivada em um assembly diferente?
Stefan Steiger
classe derivada da mesma montagem que pudermos, diferente, can't.I pensei que você quis dizer como no mesmo conjunto ...
Arun Bertil
1
@ BᴇrtiL: Hmm, certo, isso deve realmente ser chocado.
Stefan Steiger
1
Eu acho que há um erro no diagrama. Se interno for usado para uma classe, a classe poderá ser derivada por outra classe no mesmo assembly. Além disso, se o modificador interno for usado em uma propriedade, essa propriedade também poderá ser acessada na classe derivada no mesmo assembly. Talvez o diagrama esteja correto porque existe um "sim" em "contendo montagem", mas pode ser mal compreendido porque há um "não" em "classes derivadas".
AH.
160

Público - Se você pode ver a classe, pode ver o método

Privado - Se você faz parte da classe, pode ver o método, caso contrário não.

Protegido - O mesmo que Privado, e todos os descendentes também podem ver o método.

Estático (classe) - Lembra da distinção entre "Classe" e "Objeto"? Esqueça tudo isso. Eles são os mesmos com "estático" ... a classe é a única instância de si mesma.

Estático (método) - Sempre que você usar esse método, ele terá um quadro de referência independente da instância real da classe da qual faz parte.

JosephStyons
fonte
1
Você não pode ter métodos estáticos em uma classe não estática?
John Bubriski
1
Sim, mas eu estava falando sobre uma classe estática. Eu adicionei uma entrada separada para descrever métodos estáticos. Obrigado pela captura.
31410 JosephStyons
2
'Objeto' pode não ser um bom termo aqui quando se fala de C #, pois o tipo base para todas as classes é System.Object . 'Instância' seria uma palavra melhor ou 'objeto' (minúsculo 'O').
lesderid
@lesderid 'object' é um apelido para 'System.Object', usá-lo também pode ser confuso. 'instância' seria melhor, eu acho :)
DPP
mesmas regras se aplicam às estruturas.
Gsharp
35

Reposicionando os diagramas impressionantes desta resposta .

Aqui estão todos os modificadores de acesso nos diagramas de Venn, de mais limitantes a mais promíscuos:

private:
insira a descrição da imagem aqui

private protected: - adicionado no C # 7.2
insira a descrição da imagem aqui

internal:
insira a descrição da imagem aqui

protected:
insira a descrição da imagem aqui

protected internal:
insira a descrição da imagem aqui

public:
insira a descrição da imagem aqui

Paulo
fonte
24

insira a descrição da imagem aqui

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
fonte
1
Não vejo o que essa resposta agrega nas muitas outras respostas dos últimos cinco anos.
John Saunders
4
Esta é apenas uma explicação simples. Como outras respostas são pouco confuso e metade respondeu :)
Narottam Goyal
4
@ John Saunders: Diferencia separando a visibilidade de uma classe derivada entre a classe que está na mesma e a classe que está em uma montagem diferente. Além disso, ele fornece como chegou a essas informações, mostrando seu código de amostra. Então, na verdade, isso adiciona outras respostas. Sua necromancia provavelmente foi desencadeada pelo meu comentário na minha resposta.
Stefan Steiger
2
"Classe derivada em montagem diferente" - isso agrega valor ao gráfico já fornecido em outra resposta. A diferença é útil especialmente em caso de "interna protegida"
Nirman
Acho que este gráfico é o mais fácil para eu entender. Para manter essa corrente (com C # 7.2), para adicionar Private Protected, seria: mesma classe = Yes, mesma montagem, classe derivada = Yes, mesma montagem, qualquer classe = NO, montagem diferente, classe derivada = NO, montagem diferente, qualquer classe = NO. Uma sugestão adicional também seria não mudar a ordem das palavras protected internal, pois isso interrompe o pneumônico da resposta de @ user1810087
Intrastellar Explorer
22

Em relação à questão do Nada

  • Tipos de namespace são internos por padrão
  • Qualquer membro do tipo, incluindo tipos aninhados, é privado por padrão
leppie
fonte
15

Mais uma abordagem visual do atual modificador de acesso (C # 7.2). Espero que o esquema ajude a lembrá-lo com mais facilidade
(clique na imagem para visualização interativa.)

modificadores de acesso interativo svg

Fora dentro

Se você se esforçar para lembrar os modificadores de acesso de duas palavras, lembre - se de fora para dentro .

  • private protected : privado externo (o mesmo conjunto) protegido interno (mesmo conjunto)
  • interno protegido : externo protegido (o mesmo conjunto) interno interno (mesmo conjunto)
user1810087
fonte
11

Hmm.

Veja aqui: Modificadores de acesso .

Em poucas palavras:

Público fornece ao método ou tipo visibilidade completa de outros tipos / classes.

Privado permite apenas o tipo que contém o método / variável privado acesso ao método / variável privado (observe que as classes aninhadas também têm acesso aos métodos / variáveis ​​privados das classes que os contêm).

Protected é semelhante ao privado, exceto que as classes derivadas também podem acessar métodos protegidos.

"Nothing" é equivalente a VB.NET para null. Embora se você esteja se referindo a "nothing", significando "no modificador de acesso", isso depende, embora uma regra geral bastante rígida (certamente em C #) seja que, se você não especificar explicitamente um modificador de acesso, o método / variável declaração é geralmente tão restrita quanto possível. ie

public class MyClass
{
    string s = "";
}

é efetivamente o mesmo que:

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

O artigo vinculado do MSDN oferecerá uma descrição completa quando não houver um modificador de acesso especificado explicitamente.

CraigTP
fonte
8

público - pode ser acessado por qualquer pessoa em qualquer lugar.
privado - só pode ser acessado com na classe da qual faz parte.
protected - só pode ser acessado com na classe ou em qualquer objeto que herda da classe.

Nada é como nulo, mas no VB.
Estático significa que você tem uma instância desse objeto, método para todas as instâncias dessa classe.

Tony
fonte
4

mmm ...

Estático significa que você pode acessar essa função sem ter uma instância da classe.

Você pode acessar diretamente da definição de classe.

gbianchi
fonte
4

Um status de Privado indica que variáveis ​​só podem ser acessadas por objetos da mesma classe. O status protegido estende esse acesso para incluir também descendentes da classe.

"da tabela acima, podemos ver a deferência entre privado e protegido ... acho que os dois são iguais ... então qual é a necessidade desse comando em separado"

Verifique o link do MSDN para obter mais informações

Grant Hood
fonte
3

Esses modificadores de acesso especificam onde seus membros são visíveis. Você provavelmente deveria ler isso. Tome o link fornecido pelo IainMH como ponto de partida.

Os membros estáticos são um por classe e não um por instância.

jpfollenius
fonte
3

Cuidado com a acessibilidade de suas aulas. Classes e métodos públicos e protegidos são, por padrão, acessíveis a todos.

Além disso, a Microsoft não é muito explícita ao mostrar modificadores de acesso (palavras-chave públicas, protegidas etc.) quando novas classes no Visual Studio são criadas. Portanto, tome muito cuidado e pense em sua acessibilidade à sua turma, porque é a porta para seus aspectos internos de implementação.

Patrick Peters
fonte
2

Eu acho que está relacionado ao bom design de POO. Se você é desenvolvedor de uma biblioteca, deseja ocultar o funcionamento interno da sua biblioteca. Dessa forma, você pode modificar o funcionamento interno da sua biblioteca posteriormente. Portanto, você coloca seus membros e métodos auxiliares como privados e apenas os métodos de interface são públicos. Os métodos que devem ser substituídos devem ser protegidos.

Darius Kucinskas
fonte
1

C # tem no total 6 modificadores de acesso:

privado : o membro declarado com esta acessibilidade pode ser visível dentro do tipo que contém, não é visível para nenhum tipo derivado, outros tipos no mesmo conjunto ou tipos fora do conjunto que o contém. ou seja, o acesso é limitado apenas ao tipo de contenção.

protected : O membro declarado com essa acessibilidade pode ser visível dentro dos tipos derivados do tipo que contém dentro do assembly que contém e os tipos derivados do tipo que contém fora do assembly que contém. ou seja, o acesso é limitado a tipos derivados do tipo que contém.

interno : o membro declarado com essa acessibilidade pode ser visível dentro da montagem que contém esse membro, não é visível para nenhuma montagem fora da montagem que o contém. ou seja, o acesso é limitado a conter apenas montagem.

protegido interno : o membro declarado com essa acessibilidade pode ser visível dentro dos tipos derivados do tipo que contém dentro ou fora do conjunto que o contém, também é visível para todos os tipos dentro do conjunto que o contém. ou seja, o acesso é limitado a conter montagem ou tipos derivados.

público : o membro declarado com essa acessibilidade pode estar visível no assembly que contém esse membro ou em qualquer outro assembly que faça referência ao assembly que o contém. ou seja, o acesso não é limitado.

O C # 7.2 está adicionando um novo nível de acessibilidade:

private protected : O membro declarado com esta acessibilidade pode ser visível nos tipos derivados desse tipo que contém no assembly que o contém. Não é visível para nenhum tipo não derivado do tipo que contém ou fora do conjunto que o contém. ou seja, o acesso é limitado a tipos derivados no assembly que o contém.

Fonte, incluindo um código de amostra do novo modificador de acesso protegido privado

Baccata
fonte
0

Todas as descrições dos modificadores de acesso para C #

insira a descrição da imagem aqui

snr
fonte