En C #, ¿cuál es la diferencia entre público, privado, protegido y sin modificador de acceso?

728

Todos mis años de universidad he estado utilizando public, y les gustaría saber la diferencia entre public, privatey protected?

Además, ¿qué hace staticen lugar de no tener nada?

MrM
fuente

Respuestas:

1008

Modificadores de acceso

Desde docs.microsoft.com :

public

Se puede acceder al tipo o miembro mediante cualquier otro código en el mismo ensamblado u otro ensamblado que lo haga referencia.

private

Solo se puede acceder al tipo o miembro por código en la misma clase o estructura.

protected

Solo se puede acceder al tipo o miembro por código en la misma clase o estructura, o en una clase derivada.

private protected (agregado en C # 7.2)

Solo se puede acceder al tipo o miembro por código en la misma clase o estructura, o en una clase derivada del mismo conjunto, pero no desde otro conjunto.

internal

Se puede acceder al tipo o miembro mediante cualquier código en el mismo ensamblado, pero no desde otro ensamblado.

protected internal

Se puede acceder al tipo o miembro por cualquier código en el mismo ensamblaje, o por cualquier clase derivada en otro ensamblaje.

Cuando no se establece un modificador de acceso, se utiliza un modificador de acceso predeterminado. Por lo tanto, siempre hay alguna forma de modificador de acceso, incluso si no está configurado.

static modificador

El modificador estático en una clase significa que la clase no puede ser instanciada, y que todos sus miembros son estáticos. Un miembro estático tiene una versión, independientemente de cuántas instancias de su tipo envolvente se creen.

Una clase estática es básicamente lo mismo que una clase no estática, pero hay una diferencia: una clase estática no puede ser instanciada externamente. En otras palabras, no puede usar la nueva palabra clave para crear una variable del tipo de clase. Como no hay una variable de instancia, puede acceder a los miembros de una clase estática utilizando el nombre de la clase en sí.

Sin embargo, existe un constructor estático . Cualquier clase puede tener uno de estos, incluidas las clases estáticas. No se pueden llamar directamente y no pueden tener parámetros (que no sean parámetros de tipo en la clase misma). Se llama automáticamente a un constructor estático para inicializar la clase antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático. Se ve como esto:

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

    public static string Bar { get; set; }
}

Las clases estáticas a menudo se usan como servicios, puede usarlas así:

MyStaticClass.ServiceMethod(...);
mbillard
fuente
17
Y puedes tener métodos estáticos en clases no estáticas, ¿verdad?
John Bubriski
14
Sí, se comportarían de la misma manera que en mi ejemplo.
mbillard 05 de
77
¿Qué significa el término "asamblea" en este contexto?
Jonathan Gleason
1
@gotoVoid Lo que buscaste en Google es incorrecto. Según MSDN , interno protegido significa que "se puede acceder al tipo o miembro mediante cualquier código en el ensamblado en el que se declara, o desde una clase derivada en otro ensamblado".
Kevin
2
¿Cuál es la diferencia entre Protected y Private Protected? Para mí, parece que ambos son iguales ..
goofyui
161

Una descripción gráfica (resumen en pocas palabras)

Visibilidad

Como las clases estáticas están selladas, no se pueden heredar (excepto de Object), por lo que la palabra clave protegida no es válida en las clases estáticas.



Para conocer los valores predeterminados si no pone un modificador de acceso al frente, consulte aquí: ¿
Visibilidad predeterminada para clases y miembros de C # (campos, métodos, etc.)?

No anidado

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

Anidado:

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

Además, están las palabras clave selladas, lo que hace que una clase no sea heredable.
Además, en VB.NET, las palabras clave a veces son diferentes, así que aquí hay una hoja de trucos:

VB vs. CS equivalentes

Stefan Steiger
fuente
1
@ ᴇn BᴇrtiL: ¿Estás seguro? ¿Una clase derivada en un ensamblaje diferente?
Stefan Steiger
clase derivada en el mismo ensamblaje que podemos, diferentes que no podemos. Pensé que querías decir como en el mismo ensamblaje ...
Arun Bertil
1
@ ᴇn BᴇrtiL: Hmm, cierto, esto realmente debería tramarse.
Stefan Steiger
1
Creo que hay un error en el diagrama. Si se usa interno para una clase, la clase puede ser derivada por otra clase en el mismo ensamblado. Además, si el modificador interno se usa en una propiedad, también se puede acceder a esta propiedad en la clase derivada en el mismo ensamblado. Quizás el diagrama sea correcto porque hay un "sí" debajo de "que contiene el ensamblado", pero puede malinterpretarse porque hay un "no" debajo de "clases derivadas".
AH.
160

Público : si puede ver la clase, puede ver el método

Privado : si forma parte de la clase, puede ver el método; de lo contrario, no.

Protegido : igual que Privado, además de todos los descendientes también pueden ver el método.

Estática (clase) : ¿recuerda la distinción entre "Clase" y "Objeto"? Olvida todo eso. Son lo mismo con "estática" ... la clase es la única instancia de sí misma.

Estático (método) : siempre que utilice este método, tendrá un marco de referencia independiente de la instancia real de la clase de la que forma parte.

JosephStyons
fuente
1
¿No puedes tener métodos estáticos en una clase no estática?
John Bubriski
1
Sí, pero estaba hablando de una clase estática. Agregué una entrada separada para describir los métodos estáticos. Gracias por la captura.
JosephStyons 05 de
2
'Objeto' podría no ser un buen término aquí cuando se habla de C #, ya que el tipo base para todas las clases es System.Object . 'Instancia' sería una palabra mejor, u 'objeto' ('O' minúscula).
lesderid
@lesderid 'object' es un alias de 'System.Object', usarlo también puede ser confuso. 'instancia' sería mejor, supongo :)
dpp
las mismas reglas se aplican a las estructuras.
gsharp
35

Reposicionando los impresionantes diagramas de esta respuesta .

Aquí están todos los modificadores de acceso en los diagramas de Venn, desde más limitantes hasta más promiscuos:

private:
ingrese la descripción de la imagen aquí

private protected: - agregado en C # 7.2
ingrese la descripción de la imagen aquí

internal:
ingrese la descripción de la imagen aquí

protected:
ingrese la descripción de la imagen aquí

protected internal:
ingrese la descripción de la imagen aquí

public:
ingrese la descripción de la imagen aquí

Pablo
fuente
24

ingrese la descripción de la imagen aquí

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
fuente
1
No veo qué agrega esta respuesta sobre las muchas otras respuestas de los últimos cinco años.
John Saunders
44
Esta es solo una explicación simple. Como otras respuestas son un poco confusas y medio respondidas :)
Narottam Goyal
44
@ John Saunders: Se diferencia al separar la visibilidad para una clase derivada entre esa clase que está en la misma y esa clase que está en un ensamblaje diferente. Además, proporciona cómo llegó a esa información mostrando su código de muestra. Por lo tanto, en realidad se suma a las otras respuestas. Su nigromancia probablemente fue provocada por mi comentario en mi respuesta.
Stefan Steiger
2
"Clase derivada en un ensamblaje diferente": esto agrega valor al gráfico ya dado en otra respuesta. La diferencia es útil especialmente en caso de "protección interna"
Nirman
Considero que esta tabla es la más fácil de entender. Para mantener esto actual (con C # 7.2), para agregar Private Protected, sería: misma clase = Yes, mismo ensamblaje, clase derivada = Yes, mismo ensamblaje, cualquier clase = NO, ensamblaje diferente, clase derivada = NO, ensamblaje diferente, cualquier clase = NO. Una sugerencia adicional también sería no cambiar el orden de las palabras protected internal, ya que esto rompe el neumónico de la respuesta de @ user1810087
Intrastellar Explorer
22

Sobre la cuestión de Nada

  • Los tipos de espacio de nombres son internos por defecto
  • Cualquier miembro de tipo, incluidos los tipos anidados, son privados de forma predeterminada
leppie
fuente
15

Otro enfoque visual del modificador de acceso actual (C # 7.2). Esperemos que el esquema ayude a recordarlo más fácilmente
(haga clic en la imagen para una vista interactiva).

modificadores de acceso interactivo svg

Fuera dentro

Si te cuesta recordar los modificadores de acceso de dos palabras, recuerda afuera-adentro .

  • privado protegido : privado fuera (el mismo conjunto) protegido dentro (mismo conjunto)
  • Protegido interno : protegido fuera (el mismo conjunto) interno dentro (mismo conjunto)
usuario1810087
fuente
11

Hmm

Ver aquí: modificadores de acceso .

En una palabra:

Public le da al método o tipo visibilidad completa de otros tipos / clases.

Privado permite solo el tipo que contiene el método privado / variable de acceso al método privado / variable (tenga en cuenta que las clases anidadas también tienen acceso a las clases privadas que contienen métodos / variables).

Protegido es similar a privado, excepto que las clases derivadas también pueden acceder a métodos protegidos.

"Nothing" es el equivalente de VB.NET a nulo. Aunque si se refiere a "nada" que significa "sin modificador de acceso", entonces depende, aunque una regla general muy burda (ciertamente en C #) es que si no especifica explícitamente un modificador de acceso, el método / variable La declaración suele ser tan restringida como puede ser. es decir

public class MyClass
{
    string s = "";
}

es efectivamente lo mismo que:

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

El artículo de MSDN vinculado ofrecerá una descripción completa cuando no haya un modificador de acceso especificado explícitamente.

CraigTP
fuente
8

público : cualquier persona puede acceder a él desde cualquier lugar.
privado : solo se puede acceder desde con en la clase de la que forma parte.
protegido : solo se puede acceder desde con en la clase o cualquier objeto que herede fuera de la clase.

Nada es como nulo pero en VB.
Estático significa que tiene una instancia de ese objeto, método para cada instancia de esa clase.

Tony
fuente
4

mmm ...

Estático significa que puede acceder a esa función sin tener una instancia de la clase.

Puede acceder directamente desde la definición de clase.

gbianchi
fuente
4

Un estado de Privado indica que solo los objetos de la misma clase pueden acceder a las variables. El estado protegido extiende ese acceso para incluir también a los descendientes de la clase.

"de la tabla anterior podemos ver la deferencia entre privado y protegido ... creo que ambos son iguales ... entonces, ¿cuál es la necesidad de esos dos comandos separados?"

Consulte el enlace de MSDN para obtener más información.

Grant Hood
fuente
3

Esos modificadores de acceso especifican dónde están visibles sus miembros. Probablemente deberías leer esto. Tome el enlace dado por IainMH como punto de partida.

Los miembros estáticos son uno por clase y no uno por instancia.

jpfollenius
fuente
3

Cuida tu accesibilidad a tus clases. Las clases y métodos públicos y protegidos son accesibles de forma predeterminada para todos.

Además, Microsoft no es muy explícito al mostrar modificadores de acceso (palabras clave públicas, protegidas, etc.) cuando se crean nuevas clases en Visual Studio. Por lo tanto, tenga mucho cuidado y piense en la accesibilidad de su clase porque es la puerta a sus aspectos internos de implementación.

Patrick Peters
fuente
2

Creo que está relacionado con un buen diseño de OOP. Si es desarrollador de una biblioteca, desea ocultar el funcionamiento interno de su biblioteca. De esa manera, puede modificar el funcionamiento interno de su biblioteca más adelante. Así que pones tus miembros y métodos auxiliares como privados, y solo los métodos de interfaz son públicos. Los métodos que deben sobrescribirse deben protegerse.

Darius Kucinskas
fuente
1

C # tiene en total 6 modificadores de acceso:

privado : el miembro declarado con esta accesibilidad puede ser visible dentro del tipo contenedor, no está visible para ningún tipo derivado, otros tipos en el mismo ensamblaje o tipos fuera del ensamblaje contenedor. es decir, el acceso está limitado solo al tipo que lo contiene.

protegido : el miembro declarado con esta accesibilidad puede ser visible dentro de los tipos derivados del tipo contenedor dentro del ensamblaje contenedor, y los tipos derivados del tipo contenedor externo al ensamblaje contenedor. es decir, el acceso está limitado a los tipos derivados del tipo que lo contiene.

interno : el miembro declarado con esta accesibilidad puede ser visible dentro del ensamblado que contiene este miembro, no es visible para ningún ensamblaje fuera del ensamblaje que lo contiene. es decir, el acceso está limitado a contener solo el ensamblaje.

Protección interna : el miembro declarado con esta accesibilidad puede ser visible dentro de los tipos derivados del tipo que contiene dentro o fuera del ensamblaje que lo contiene, también es visible para cualquier tipo dentro del ensamblaje que lo contiene. es decir, el acceso está limitado a contener ensamblaje o tipos derivados.

public : El miembro declarado con esta accesibilidad puede ser visible dentro del ensamblado que contiene este miembro, o cualquier otro ensamblado que haga referencia al ensamblaje que lo contiene. es decir, el acceso no es limitado.

C # 7.2 está agregando un nuevo nivel de accesibilidad:

privado protegido : el miembro declarado con esta accesibilidad puede ser visible dentro de los tipos derivados de este tipo que contiene dentro del conjunto contenedor. No es visible para ningún tipo que no se derive del tipo que lo contiene, o que esté fuera del ensamblaje que lo contiene. es decir, el acceso está limitado a los tipos derivados dentro del conjunto contenedor.

Fuente que incluye un código de muestra del nuevo modificador de acceso protegido privado

Baccata
fuente
0

Descripciones de todos los modificadores de acceso para C #

ingrese la descripción de la imagen aquí

snr
fuente