了解 C# 访问修饰符
在本文中,我们将深入探讨 C# 访问修饰符,它定义了 C# 中类型、方法和变量的可见性和可访问性。 Tim Corey 在他的视频" C# 访问修饰符(超越 public 和 private)- 它们是什么、如何使用它们以及最佳实践"中解释了各种访问修饰符,并在控制台应用程序中演示了它们的实际用法。
本文将解释 Tim 所讲解的内容,并提供代码示例以加深您的理解。 提供的时间戳可让您跟随视频进行操作,从而获得更实际的体验。
什么是访问修饰符?
介绍
Tim Corey 首先介绍了访问修饰符,并解释说它们决定了谁可以在 C# 中查看和使用资源。 虽然我们熟悉常用的公共和私有修饰符,但 Tim 探讨了六种不同的访问修饰符及其使用案例。
演示应用程序详解
Tim 创建了一个简单的应用程序来演示各种访问修饰符的工作原理。 该应用程序由控制台用户界面和演示库组成,两者均采用 .NET Framework编写。
项目结构:
*控制台 UI* :用于测试访问修饰符的控制台应用程序。 演示库**:一个用于演示不同访问修饰符的类库。
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. 私人
它是什么:
private 修饰符将方法、字段或属性的访问权限限制在定义它的类中。
代码示例:
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
}
}解释:AccessDemo类内可访问。 在视频中,Tim 演示了即使其他类在同一个项目中,也无法从类外部访问它。
最佳实践:当您想要限制对类的内部运作的访问时,请使用 private,以确保它不能从应用程序的其他部分直接更改。
2. 内部
它是什么:
内部修饰符仅允许在同一程序集(项目)内访问方法或属性。 这比私有访问修饰符的范围更广,因为它包括同一项目中的所有类。
代码示例:
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.");
}
}解释:InternalDemo方法可以被同一程序集内的任何类访问,但其他程序集不可访问。 在视频中,Tim 展示了内部权限允许访问同一项目内部,但拒绝从外部访问。
最佳实践:对于仅供当前程序集内使用的方法或属性,例如不应向外部项目公开的辅助函数或实用程序,请使用 internal。
3. 公众
它是什么:
public 修饰符允许从任何其他类或程序集访问方法或属性。 这是权限最高的访问级别。
代码示例:
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.");
}
}解释:PublicDemo方法从任何地方都可访问,包括同一程序集中的其他类或其他程序集。 Tim 证明 public 是最常见的访问修饰符,尤其是在公开库中的方法时。
最佳实践:对于需要被应用程序其他部分或外部项目(例如 API 端点或广泛使用的实用程序)访问的方法和属性,请使用 public。
4. 受保护的
它是什么:
protected 修饰符允许访问定义该方法或属性的类中的方法或属性,以及任何派生类(继承)中的方法或属性。 该修饰符对面向对象编程非常有用,尤其是在继承的情况下。
代码示例:
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
}
}解释:AccessDemo类及其任何继承类中访问。 Tim解释说,受保护的继承方式虽然不太常见,但在处理继承问题时非常有用。
最佳实践:当您希望允许派生类访问特定方法或属性,但不希望它们在类层次结构之外可访问时,请使用 protected。
5. 私人保护
它是什么:
私有受保护修饰符结合了私有和受保护的规则。 它限制对定义类和同一程序集中的派生类中的方法或属性的访问。 这意味着与受保护的访问控制相比,它提供了更高的保护级别和更严格的基于继承的访问控制边界。
代码示例:
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
}
}解释:由于继承自DerivedClass中是可访问的。 然而,它在AccessDemo。
最佳实践:当需要严格控制同一程序集中的继承访问时,应谨慎使用私有受保护访问修饰符。 这在跨程序集公开方法或属性可能会破坏封装性的场景中尤其有用。
6. 受保护的内部
它是什么:
受保护的内部修饰符结合了受保护和内部访问修饰符级别。 它允许从同一个程序集或派生类进行访问,即使它们位于另一个程序集中。
代码示例:
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
}
}解释:ProtectedInternalDemo方法可以在同一程序集内访问,也可以从任何派生类访问,而不论程序集。
最佳实践:当你想要将一个方法同时暴露给派生类(在其他程序集中)和同一程序集中的类,但又不想暴露给所有人时,请使用 protected internal。
为什么不把所有事情都公开呢?
Tim Corey 解释了使用访问修饰符的重要性,以及为什么不应该把所有内容都设为公开。 虽然将所有内容公开似乎很方便,但这会带来重大风险,包括数据泄露、漏洞和开发过程中的混乱。 访问修饰符的存在是为了保护信息安全、防止意外的公共访问,并使代码库更加清晰。
1. 保护隐私信息
蒂姆讨论了为什么社会安全号码(SSN)或信用卡号码等敏感信息不应该被公开。 他举例说明了"不良案例",即由于公共访问而导致数据泄露:
反例:
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
}好例子:
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. 保护私有方法
开始时间:35:11 Tim解释说,私有方法有助于封装不应该直接访问的行为。 他使用DeleteUser方法作为更大过程的一部分,例如员工离职。
反例:
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
}
}好例子:
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. 防止漏洞
访问修饰符通过确保数据经过适当的验证来设置或检索,从而防止出现错误。 Tim 用包含Age属性的示例来说明这一点。
反例:
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
}好例子:
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. 减少困惑,增强清晰度
正确使用访问修饰符可以简化开发,因为它只公开必要的内容,避免混淆。 例如,在一个拥有数千个方法的应用程序中,只公开方法可以确保开发人员只看到相关的选项。
示例:
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. 在大型应用程序或库中的优势
Tim 解释说,对于大型项目,正确使用访问修饰符可以确保只公开库的必要部分,从而减轻使用该库的开发人员的认知负担。
示例:
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
}
}正确使用这些访问修饰符,可以让你的工作和下一个人的工作变得更轻松。
结论
Tim Corey 提供了一份清晰实用的指南,指导读者掌握 C# 访问修饰符,并展示了如何有效地使用它们来创建安全、可维护和专业的应用程序。 他详尽的解释和真实案例使各个级别的开发人员都能理解这个主题。
想要更深入地了解这些概念并了解它们的实际应用,请务必观看 Tim 的完整视频,并浏览他的频道,获取有关 C# 和其他编程主题的宝贵内容。 对于任何认真想要提高开发技能的人来说,这都是一个必看的资源!

