Entendendo os Modificadores de Acesso em C#
Neste artigo, vamos explorar os modificadores de acesso em C#, que definem a visibilidade e a acessibilidade de tipos, métodos e variáveis em C#. Em seu vídeo " Modificadores de acesso em C# (além de public e private) - o que são, como usá-los e melhores práticas ", Tim Corey explica vários modificadores de acesso e demonstra seu uso prático em um aplicativo de console.
Este artigo explicará o que Tim abordou, juntamente com exemplos de código para aprimorar sua compreensão. Os marcadores de tempo fornecidos permitem que você acompanhe o vídeo para uma experiência mais prática.
O que são modificadores de acesso?
Introdução
Tim Corey começa apresentando os modificadores de acesso, explicando que eles determinam quem pode ver e usar um recurso em C#. Embora estejamos familiarizados com os modificadores públicos e privados comumente usados, Tim explora seis modificadores de acesso diferentes e seus casos de uso.
Explicação do aplicativo de demonstração
Tim cria um aplicativo simples para demonstrar como funcionam os diversos modificadores de acesso. A aplicação consiste em uma interface de usuário de console e uma biblioteca de demonstração, ambas em .NET Framework.
Estrutura do projeto:
- Interface de usuário do console : um aplicativo de console para testar modificadores de acesso.
- Biblioteca de Demonstração : Uma biblioteca de classes onde diferentes modificadores de acesso são demonstrados.
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}
1. Particular
O que é:
O modificador private restringe o acesso ao método, campo ou propriedade somente dentro da classe onde ele está definido.
Exemplo de código:
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}
Explicação: O método PrivateDemo é acessível apenas dentro da classe AccessDemo. No vídeo, Tim demonstra que não é possível acessar o recurso de fora da classe, mesmo que outras classes estejam no mesmo projeto.
Boa prática : Use private quando quiser restringir o acesso ao funcionamento interno da sua classe, garantindo que ela não possa ser alterada diretamente por outras partes da sua aplicação.
2. Interno
O que é:
O modificador interno permite o acesso ao método ou propriedade somente dentro do mesmo assembly (o projeto). Isso é mais abrangente do que o modificador de acesso privado, pois inclui todas as classes dentro do mesmo projeto.
Exemplo de código:
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}
Explicação: O método InternalDemo pode ser acessado por qualquer classe dentro do mesmo assembly, mas não de outros assemblies. No vídeo, Tim mostra que o acesso interno é permitido dentro do mesmo projeto, mas o acesso externo é negado.
Boa prática : Use internal para métodos ou propriedades que devem ser usados apenas dentro do assembly atual, como funções auxiliares ou utilitários que não devem ser expostos a projetos externos.
3. Público
O que é:
O modificador public permite o acesso ao método ou à propriedade a partir de qualquer outra classe ou assembly. Este é o nível de acesso mais permissivo.
Exemplo de código:
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}
Explicação: O método PublicDemo é acessível de qualquer lugar, incluindo outras classes no mesmo assembly ou em outros assemblies. Tim demonstra que public é o modificador de acesso mais comum, especialmente ao expor métodos em bibliotecas.
Boa prática : Use public para métodos e propriedades que precisam ser acessíveis por outras partes do aplicativo ou projetos externos, como endpoints de API ou utilitários amplamente utilizados.
4. Protegido
O que é:
O modificador protected permite o acesso ao método ou propriedade dentro da classe onde ele é definido e em quaisquer classes derivadas (herança). Esse modificador é útil para programação orientada a objetos, especialmente em casos de herança.
Exemplo de código:
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}
Explicação: O método ProtectedDemo pode ser acessado da classe AccessDemo e de qualquer classe que herde dela. Tim explica que "protegido" é menos comum, mas muito útil quando se trabalha com herança.
Boa prática : Use protected quando quiser permitir que classes derivadas acessem métodos ou propriedades específicos, mas não quiser que sejam acessíveis fora da hierarquia de classes.
5. Privado e Protegido
O que é:
O modificador "privado protegido" combina as regras de "privado" e "protegido". Isso restringe o acesso a métodos ou propriedades dentro da classe que define a classe e das classes derivadas dentro do mesmo assembly . Isso significa que oferece um nível de proteção adicional e limites mais rigorosos para o controle de acesso baseado em herança em comparação com o modo protegido.
Exemplo de código:
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}
Explicação: O método PrivateProtectedDemo é acessível na DerivedClass porque herda de AccessDemo e existe no mesmo assembly. No entanto, ele não pode ser acessado na UnrelatedClass, pois esta classe não herda de AccessDemo.
Boa prática : Use o modificador de acesso protegido privado com moderação, quando precisar controlar rigorosamente o acesso à herança dentro do mesmo assembly. Isso é especialmente útil em cenários onde expor métodos ou propriedades entre assemblies pode comprometer o encapsulamento.
6. Interno Protegido
O que é:
O modificador interno protegido combina os níveis de modificador de acesso protegido e interno. Permite o acesso a partir do mesmo assembly ou de classes derivadas, mesmo que estejam em outro assembly.
Exemplo de código:
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}
Explicação: O método ProtectedInternalDemo é acessível dentro do mesmo assembly e também de qualquer classe derivada, independentemente do assembly.
Boa prática : Use protected internal quando desejar expor um método tanto para classes derivadas (em outros assemblies) quanto para classes no mesmo assembly, mas não para todos.
Por que não tornar tudo público?
Tim Corey explica a importância de usar modificadores de acesso e por que nem tudo deve ser público. Embora tornar tudo público possa parecer conveniente, isso acarreta riscos significativos, incluindo violações de dados, erros e confusão durante o desenvolvimento. Os modificadores de acesso existem para proteger informações, impedir o acesso público não intencional e proporcionar clareza nas bases de código.
1. Protegendo informações privadas
Tim explica por que informações sensíveis, como números de Segurança Social (SSNs) ou números de cartão de crédito, não devem ser tornadas públicas. Ele demonstra um exemplo de "classe ruim" onde a exposição de dados ocorre devido ao acesso público:
Exemplo ruim:
public class User
{
public string SSN; // Anyone can access and modify it directly
}
public class User
{
public string SSN; // Anyone can access and modify it directly
}
Bom exemplo:
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}
2. Protegendo Métodos Privados
Início: 35:11
Tim explica que os métodos privados ajudam a encapsular comportamentos que não devem ser diretamente acessíveis. Ele usa o exemplo de um método DeleteUser como parte de um processo maior, como a saída de funcionários.
Exemplo ruim:
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}
Bom exemplo:
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}
3. Prevenção de erros
Os modificadores de acesso previnem erros, garantindo que os dados sejam definidos ou recuperados com a validação adequada. Tim ilustra isso com um exemplo envolvendo uma propriedade Age.
Exemplo ruim:
public class Person
{
public int Age; // Can be directly set to an invalid value
}
public class Person
{
public int Age; // Can be directly set to an invalid value
}
Bom exemplo:
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}
4. Reduzindo a Confusão e Aumentando a Clareza
O uso correto de modificadores de acesso simplifica o desenvolvimento, expondo apenas o necessário e evitando confusões. Por exemplo, em uma aplicação com milhares de métodos, expor apenas os métodos públicos garante que os desenvolvedores vejam somente as opções relevantes.
Exemplo:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
5. Benefícios em aplicações ou bibliotecas de maior porte
Para projetos de grande escala, Tim explica como o uso adequado de modificadores de acesso garante que apenas as partes necessárias de uma biblioteca sejam expostas, reduzindo a carga cognitiva para os desenvolvedores que utilizam a biblioteca.
Exemplo:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}
Ao usar esses modificadores de acesso corretamente, você facilita seu trabalho e o da próxima pessoa.
Conclusão
Tim Corey oferece um guia claro e prático para dominar os modificadores de acesso em C#, mostrando como usá-los de forma eficaz para criar aplicações seguras, de fácil manutenção e profissionais. Suas explicações detalhadas e exemplos práticos tornam este tópico acessível a desenvolvedores de todos os níveis.
Para obter informações mais detalhadas e ver esses conceitos em ação, assista ao vídeo completo de Tim e explore o canal dele para encontrar conteúdo valioso sobre C# e outros tópicos de programação. É um recurso indispensável para qualquer pessoa que leve a sério o aprimoramento de suas habilidades de desenvolvimento!
