【C#】C# 访问修饰符与类修饰符总结大全

文章目录

    • 一、访问修饰符详解
      • [1.1 访问修饰符对比表](#1.1 访问修饰符对比表)
      • [1.2 访问修饰符详细说明](#1.2 访问修饰符详细说明)
        • [**public - 公共访问**](#public - 公共访问)
        • [**private - 私有访问**](#private - 私有访问)
        • [**protected - 受保护访问**](#protected - 受保护访问)
        • [**internal - 程序集内部访问**](#internal - 程序集内部访问)
        • [**protected internal - 受保护的内部访问**](#protected internal - 受保护的内部访问)
        • [**private protected - 私有受保护访问 (C# 7.2+)**](# 7.2+)**)
      • [1.3 访问修饰符可视化对比](#1.3 访问修饰符可视化对比)
    • 二、类修饰符详解
      • [2.1 类修饰符对比表](#2.1 类修饰符对比表)
      • [2.2 类修饰符详细说明](#2.2 类修饰符详细说明)
        • [**abstract - 抽象类**](#abstract - 抽象类)
        • [**sealed - 密封类**](#sealed - 密封类)
        • [**static - 静态类**](#static - 静态类)
        • [**partial - 部分类**](#partial - 部分类)
        • [**new - 隐藏成员**](#new - 隐藏成员)
      • [2.3 修饰符组合规则](#2.3 修饰符组合规则)
    • 三、综合对比分析
      • [3.1 访问修饰符选择指南](#3.1 访问修饰符选择指南)
      • [3.2 类修饰符选择指南](#3.2 类修饰符选择指南)
      • [3.3 完整示例对比](#3.3 完整示例对比)
    • 四、实际应用示例
      • [4.1 企业级应用架构示例](#4.1 企业级应用架构示例)
      • [4.2 实际项目中的典型模式](#4.2 实际项目中的典型模式)
      • [4.3 最佳实践总结](#4.3 最佳实践总结)
    • 五、快速参考卡片
    • 六、常见问题与陷阱
      • [Q1: 为什么不能继承密封类?](#Q1: 为什么不能继承密封类?)
      • [Q2: abstract和virtual的区别?](#Q2: abstract和virtual的区别?)
      • [Q3: new和override的区别?](#Q3: new和override的区别?)
      • [Q4: 为什么不能在类内部定义protected internal成员?](#Q4: 为什么不能在类内部定义protected internal成员?)
    • 总结

一、访问修饰符详解

访问修饰符控制类型及其成员的可访问性,是封装特性的核心实现机制。

1.1 访问修饰符对比表

修饰符 访问级别 类内部 派生类 同一程序集 派生类(不同程序集) 任何代码
public 无限制
private 仅包含类
protected 派生类
internal 同一程序集
protected internal 并集
private protected 交集 ✅(同程序集)

1.2 访问修饰符详细说明

public - 公共访问
csharp 复制代码
public class PublicClass
{
    public string PublicField = "任何人都能访问";
    
    public void PublicMethod()
    {
        Console.WriteLine("公共方法可以被任何代码调用");
    }
}

// 任何地方都可以访问
var obj = new PublicClass();
obj.PublicField = "修改成功";
obj.PublicMethod();  // ✅ 可调用
private - 私有访问
csharp 复制代码
public class PrivateDemo
{
    private string _privateField = "只有本类能访问";
    private void PrivateMethod() { }
    
    public void PublicMethod()
    {
        // ✅ 类内部可以访问私有成员
        _privateField = "修改成功";
        PrivateMethod();
    }
}

// ❌ 外部无法访问私有成员
var demo = new PrivateDemo();
// demo._privateField;    // 编译错误
// demo.PrivateMethod();  // 编译错误
protected - 受保护访问
csharp 复制代码
public class Animal
{
    protected string _name = "动物";
    protected void Eat() => Console.WriteLine("吃东西");
}

public class Dog : Animal
{
    public void ShowName()
    {
        // ✅ 派生类可以访问protected成员
        Console.WriteLine($"名字: {_name}");
        Eat();  // ✅ 可调用
    }
}

// ❌ 非派生类无法访问
var animal = new Animal();
// animal._name;  // 编译错误
// animal.Eat();  // 编译错误
internal - 程序集内部访问
csharp 复制代码
// Assembly1.dll
internal class InternalClass
{
    internal string InternalField = "同程序集可访问";
}

public class PublicClass
{
    internal void InternalMethod() { }
}

// Assembly2.dll (引用Assembly1)
// ❌ 无法访问Assembly1中的internal成员
// var obj = new InternalClass();  // 编译错误
protected internal - 受保护的内部访问
csharp 复制代码
public class BaseClass
{
    protected internal string ProInternal = "程序集内或派生类可访问";
}

// 同一程序集中的类
public class SameAssemblyClass
{
    public void Test(BaseClass baseObj)
    {
        // ✅ 同程序集可以访问protected internal
        Console.WriteLine(baseObj.ProInternal);
    }
}

// 不同程序集中的派生类
public class DerivedInOtherAssembly : BaseClass
{
    public void Test()
    {
        // ✅ 派生类也可以访问
        Console.WriteLine(ProInternal);
    }
}
private protected - 私有受保护访问 (C# 7.2+)
csharp 复制代码
public class BaseClass
{
    private protected string PrivateProtected = "同程序集的派生类可访问";
}

// 同一程序集的派生类
public class DerivedInSameAssembly : BaseClass
{
    public void Test()
    {
        // ✅ 同程序集的派生类可访问
        Console.WriteLine(PrivateProtected);
    }
}

// 同一程序集的非派生类
public class NonDerivedClass
{
    public void Test(BaseClass baseObj)
    {
        // ❌ 同程序集但不是派生类,无法访问
        // Console.WriteLine(baseObj.PrivateProtected);  // 编译错误
    }
}

1.3 访问修饰符可视化对比

复制代码
访问范围对比图:

public          ┌─────────────────────────────────────┐
                │         任 何 代 码                  │
                └─────────────────────────────────────┘

protected       ┌─────────────────────────────────────┐
 internal       │    派生类 + 同一程序集               │
                └─────────────────────────────────────┘

protected       ┌─────────────────────────────────────┐
                │         派 生 类                     │
                └─────────────────────────────────────┘

internal        ┌─────────────────────────────────────┐
                │      同 一 程 序 集                  │
                └─────────────────────────────────────┘

private         ┌─────────────────────────────────────┐
 protected      │   同一程序集的派生类                 │
                └─────────────────────────────────────┘

private         ┌─────────────────────────────────────┐
                │          本 类                        │
                └─────────────────────────────────────┘

二、类修饰符详解

类修饰符控制类的行为和特性,包括继承、实例化、抽象性等。

2.1 类修饰符对比表

修饰符 作用 能修饰什么 说明
abstract 抽象类 类、方法、属性 不能实例化,可包含抽象成员
sealed 密封类 类、方法、属性 不能被继承
static 静态类 类、方法、属性 不能实例化,只包含静态成员
partial 部分类 类、结构、接口 类定义可分散在多个文件
new 隐藏成员 类、方法、属性 显式隐藏基类成员

2.2 类修饰符详细说明

abstract - 抽象类
csharp 复制代码
// 抽象类:不能实例化,可以包含抽象方法
public abstract class Shape
{
    public string Color { get; set; }
    
    // 抽象方法:没有实现,派生类必须重写
    public abstract double GetArea();
    
    // 虚方法:可以有默认实现,派生类可选重写
    public virtual void Display()
    {
        Console.WriteLine($"形状颜色: {Color}");
    }
    
    // 具体方法:有完整实现
    public void SetColor(string color)
    {
        Color = color;
    }
}

// 派生类必须实现所有抽象成员
public class Circle : Shape
{
    public double Radius { get; set; }
    
    // 必须实现抽象方法
    public override double GetArea()
    {
        return Math.PI * Radius * Radius;
    }
    
    // 可选重写虚方法
    public override void Display()
    {
        base.Display();
        Console.WriteLine($"圆形半径: {Radius}");
    }
}

// 使用示例
// Shape shape = new Shape();  // ❌ 错误:不能实例化抽象类
Circle circle = new Circle { Radius = 5, Color = "红色" };
double area = circle.GetArea();  // ✅ 正确
sealed - 密封类
csharp 复制代码
// 密封类:不能被继承
public sealed class ConfigurationManager
{
    private static ConfigurationManager _instance;
    
    private ConfigurationManager() { }
    
    public static ConfigurationManager Instance
    {
        get
        {
            if (_instance == null)
                _instance = new ConfigurationManager();
            return _instance;
        }
    }
    
    public string ConnectionString { get; set; }
}

// ❌ 错误:无法继承密封类
// public class ExtendedConfig : ConfigurationManager { }

// sealed 也可以修饰方法,防止派生类继续重写
public class BaseClass
{
    public virtual void Method1() { }
    public virtual void Method2() { }
}

public class DerivedClass : BaseClass
{
    public sealed override void Method1() { }  // 密封此方法
    public override void Method2() { }
}

public class FurtherDerived : DerivedClass
{
    // ❌ 错误:不能重写密封的方法
    // public override void Method1() { }
    
    // ✅ 正确:可以重写未密封的方法
    public override void Method2() { }
}
static - 静态类
csharp 复制代码
// 静态类:不能实例化,所有成员必须是静态的
public static class MathHelper
{
    // 静态字段
    public static double PI = 3.14159;
    
    // 静态属性
    public static double E { get; } = 2.71828;
    
    // 静态方法
    public static double CalculateCircleArea(double radius)
    {
        return PI * radius * radius;
    }
    
    // ❌ 错误:静态类不能包含实例成员
    // public string Name { get; set; }
    // public void InstanceMethod() { }
}

// 使用方式:直接通过类名调用
double area = MathHelper.CalculateCircleArea(10);
Console.WriteLine($"PI值: {MathHelper.PI}");

// MathHelper helper = new MathHelper();  // ❌ 错误:不能实例化静态类
partial - 部分类
csharp 复制代码
// File: Person.cs
public partial class Person
{
    private string _name;
    private int _age;
    
    public Person(string name, int age)
    {
        _name = name;
        _age = age;
    }
}

// File: Person.Methods.cs
public partial class Person
{
    public void Display()
    {
        Console.WriteLine($"姓名: {_name}, 年龄: {_age}");
    }
    
    public void UpdateAge(int newAge)
    {
        _age = newAge;
    }
}

// File: Person.Properties.cs
public partial class Person
{
    public string Name 
    { 
        get => _name;
        set => _name = value;
    }
    
    public int Age
    {
        get => _age;
        set => _age = value;
    }
}

// 所有部分会被编译成一个完整的类
var person = new Person("张三", 25);
person.Display();           // ✅ 来自 Person.Methods.cs
person.Name = "李四";        // ✅ 来自 Person.Properties.cs
new - 隐藏成员
csharp 复制代码
public class BaseClass
{
    public string Name = "基类名称";
    public void Display() => Console.WriteLine("基类显示");
    public virtual void Show() => Console.WriteLine("基类显示");
}

public class DerivedClass : BaseClass
{
    // new: 显式隐藏基类成员(不使用多态)
    public new string Name = "派生类名称";
    public new void Display() => Console.WriteLine("派生类显示");
    
    // override: 重写虚方法(使用多态)
    public override void Show() => Console.WriteLine("派生类显示");
}

// 使用示例
BaseClass baseRef = new DerivedClass();

Console.WriteLine(baseRef.Name);     // 输出: "基类名称" (使用基类字段)
baseRef.Display();                   // 输出: "基类显示" (调用基类方法)
baseRef.Show();                      // 输出: "派生类显示" (多态调用)

DerivedClass derivedRef = new DerivedClass();
Console.WriteLine(derivedRef.Name);  // 输出: "派生类名称"
derivedRef.Display();                // 输出: "派生类显示"

2.3 修饰符组合规则

组合 是否允许 说明
abstract class 抽象类,可包含抽象成员
sealed class 密封类,不能被继承
static class 静态类,不能实例化
abstract sealed 矛盾:既抽象又密封
abstract static 矛盾:抽象类可以有实例成员
partial class 可与任何其他修饰符组合

三、综合对比分析

3.1 访问修饰符选择指南

场景 推荐修饰符 原因
API接口 public 需要对外提供
内部实现细节 private 封装性最佳
需要派生类扩展 protected 平衡封装和扩展性
库内部共享 internal 对外隐藏实现
库内部+派生类扩展 protected internal 最大灵活性
同程序集派生类 private protected 最小暴露范围

3.2 类修饰符选择指南

设计意图 推荐修饰符 说明
定义通用契约 abstract 提供抽象基类
防止进一步继承 sealed 最终实现类
工具类 static 无状态工具方法
大型类拆分 partial 代码组织
隐藏基类成员 new 谨慎使用

3.3 完整示例对比

csharp 复制代码
// 示例1: 不同访问级别的类成员
public class BankAccount
{
    // public: 所有人都能看到余额
    public decimal Balance { get; private set; }
    
    // private: 账号是内部实现细节
    private string _accountNumber;
    
    // protected: 派生类可以修改利率
    protected decimal InterestRate = 0.03m;
    
    // internal: 同一程序集可以访问银行信息
    internal string BankName = "MyBank";
    
    // protected internal: 程序集内或派生类可访问
    protected internal string BranchCode = "001";
    
    // private protected: 仅同程序集的派生类可访问
    private protected string ManagerName = "张三";
}

// 示例2: 不同类修饰符的类
public abstract class Vehicle          // 抽象类
{
    public abstract void Start();
}

public sealed class Car : Vehicle      // 密封类,继承抽象类
{
    public override void Start()
    {
        Console.WriteLine("汽车启动");
    }
}

public static class VehicleFactory     // 静态类
{
    public static Car CreateCar() => new Car();
}

// 示例3: 部分类实现复杂功能
public partial class DataProcessor
{
    private string _data;
    
    public DataProcessor(string data)
    {
        _data = data;
    }
}

public partial class DataProcessor
{
    public string Process()
    {
        return _data.ToUpper();
    }
    
    public string Validate()
    {
        return string.IsNullOrEmpty(_data) ? "无效" : "有效";
    }
}

四、实际应用示例

4.1 企业级应用架构示例

csharp 复制代码
using System;
using System.Collections.Generic;

namespace EnterpriseApplication
{
    #region 领域模型层 (Domain Layer)
    
    // 抽象基类:定义领域实体的公共行为
    public abstract class Entity
    {
        public int Id { get; protected set; }
        public DateTime CreatedAt { get; private set; }
        
        protected Entity()
        {
            CreatedAt = DateTime.Now;
        }
        
        // 抽象方法:派生类必须实现业务规则
        public abstract bool IsValid();
        
        // 虚方法:提供默认实现,派生类可选重写
        public virtual string GetDisplayName() => $"Entity-{Id}";
    }
    
    // 具体实体类
    public sealed class Product : Entity  // sealed: 不允许进一步继承
    {
        public string Name { get; private set; }
        public decimal Price { get; private set; }
        
        // 构造函数:internal确保只能在程序集内创建
        internal Product(string name, decimal price)
        {
            Name = name;
            Price = price;
        }
        
        public override bool IsValid()
        {
            return !string.IsNullOrEmpty(Name) && Price > 0;
        }
        
        public override string GetDisplayName() => Name;
        
        // 业务方法
        public void UpdatePrice(decimal newPrice)
        {
            if (newPrice <= 0)
                throw new ArgumentException("价格必须大于0");
            Price = newPrice;
        }
    }
    
    #endregion
    
    #region 仓储层 (Repository Layer)
    
    // 接口:定义契约
    public interface IRepository<T> where T : Entity
    {
        T GetById(int id);
        IEnumerable<T> GetAll();
        void Add(T entity);
        void Update(T entity);
        void Delete(int id);
    }
    
    // 抽象基类:提供通用实现
    public abstract class BaseRepository<T> : IRepository<T> 
        where T : Entity
    {
        protected readonly List<T> _entities = new List<T>();
        
        public virtual T GetById(int id) => 
            _entities.Find(e => e.Id == id);
        
        public virtual IEnumerable<T> GetAll() => _entities;
        
        public abstract void Add(T entity);
        public virtual void Update(T entity) { }
        public virtual void Delete(int id) { }
    }
    
    // 具体实现:internal隐藏实现细节
    internal class ProductRepository : BaseRepository<Product>
    {
        private static int _nextId = 1;
        
        public override void Add(Product entity)
        {
            // 使用反射设置Id(实际项目中应使用更好的方式)
            typeof(Entity).GetProperty("Id")?
                .SetValue(entity, _nextId++);
            _entities.Add(entity);
        }
        
        // protected internal: 程序集内的其他类可以访问此方法
        protected internal void ClearAll() => _entities.Clear();
        
        // private protected: 仅同程序集的派生类可访问
        private protected void LogOperation(string operation)
        {
            Console.WriteLine($"[日志] {operation} 操作执行");
        }
    }
    
    #endregion
    
    #region 服务层 (Service Layer)
    
    // 静态工具类:提供扩展方法
    public static class RepositoryExtensions
    {
        public static bool Exists<T>(this IRepository<T> repository, int id) 
            where T : Entity
        {
            return repository.GetById(id) != null;
        }
    }
    
    // 业务服务类
    public class ProductService
    {
        private readonly IRepository<Product> _repository;
        
        public ProductService(IRepository<Product> repository)
        {
            _repository = repository;
        }
        
        public void CreateProduct(string name, decimal price)
        {
            var product = new Product(name, price);
            if (!product.IsValid())
                throw new InvalidOperationException("产品信息无效");
            
            _repository.Add(product);
            Console.WriteLine($"产品 {name} 创建成功");
        }
        
        public void DisplayAllProducts()
        {
            var products = _repository.GetAll();
            Console.WriteLine("\n产品列表:");
            foreach (var product in products)
            {
                Console.WriteLine($"  {product.GetDisplayName()} - {product.Price:C}");
            }
        }
    }
    
    #endregion
    
    #region 表示层 (Presentation Layer)
    
    // 部分类:WinForm设计器生成的代码和业务逻辑分离
    public partial class ProductForm : Form
    {
        private readonly ProductService _service;
        
        public ProductForm()
        {
            InitializeComponent();  // 在另一个部分类文件中
            _service = new ProductService(new ProductRepository());
        }
        
        private void btnCreate_Click(object sender, EventArgs e)
        {
            try
            {
                _service.CreateProduct(txtName.Text, decimal.Parse(txtPrice.Text));
                _service.DisplayAllProducts();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"错误: {ex.Message}");
            }
        }
    }
    
    // 部分类的另一部分(通常由设计器生成)
    public partial class ProductForm
    {
        private System.Windows.Forms.TextBox txtName;
        private System.Windows.Forms.TextBox txtPrice;
        private System.Windows.Forms.Button btnCreate;
        
        private void InitializeComponent()
        {
            txtName = new TextBox();
            txtPrice = new TextBox();
            btnCreate = new Button();
            // 控件初始化代码...
        }
    }
    
    #endregion
    
    #region 测试类
    
    class Program
    {
        static void Main(string[] args)
        {
            // 演示访问修饰符效果
            var repository = new ProductRepository();  // 同一程序集可访问internal类
            var service = new ProductService(repository);
            
            service.CreateProduct("笔记本电脑", 5999.99m);
            service.CreateProduct("鼠标", 99.99m);
            service.DisplayAllProducts();
            
            // 演示static类使用
            var exists = repository.Exists(1);  // 使用扩展方法
            
            Console.WriteLine($"\n产品1存在: {exists}");
        }
    }
    
    #endregion
}

4.2 实际项目中的典型模式

csharp 复制代码
// 1. 单例模式 - 使用sealed和private
public sealed class Configuration
{
    private static readonly Configuration _instance = new Configuration();
    private Configuration() { }  // private构造函数防止外部实例化
    public static Configuration Instance => _instance;
    
    public string ConnectionString { get; set; }
}

// 2. 工厂模式 - 使用internal和public
public interface ILogger
{
    void Log(string message);
}

internal class FileLogger : ILogger  // internal隐藏实现
{
    public void Log(string message) => File.AppendAllText("log.txt", message);
}

internal class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine(message);
}

public static class LoggerFactory  // public静态工厂
{
    public static ILogger CreateFileLogger() => new FileLogger();
    public static ILogger CreateConsoleLogger() => new ConsoleLogger();
}

// 3. 模板方法模式 - 使用abstract和protected
public abstract class DataExporter
{
    // 模板方法
    public void Export()
    {
        Connect();
        ExtractData();
        TransformData();
        WriteOutput();
        Disconnect();
    }
    
    // 公共方法,所有派生类共享
    private void Connect() => Console.WriteLine("连接数据库");
    private void Disconnect() => Console.WriteLine("断开连接");
    
    // 派生类必须实现的抽象方法
    protected abstract void ExtractData();
    protected abstract void TransformData();
    protected abstract void WriteOutput();
}

public class ExcelExporter : DataExporter
{
    protected override void ExtractData() => Console.WriteLine("提取Excel数据");
    protected override void TransformData() => Console.WriteLine("转换Excel格式");
    protected override void WriteOutput() => Console.WriteLine("写入Excel文件");
}

// 4. 扩展方法 - 使用static类
public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string str) => string.IsNullOrEmpty(str);
    public static string ToTitleCase(this string str) => 
        str.Substring(0, 1).ToUpper() + str.Substring(1).ToLower();
}

4.3 最佳实践总结

csharp 复制代码
public class BestPracticesDemo
{
    // ✅ 好的实践:最小权限原则
    private string _privateField;          // 尽可能使用private
    protected string _protectedField;       // 需要派生类访问时使用protected
    internal string _internalField;         // 同一程序集共享时使用internal
    
    // ✅ 好的实践:属性暴露,字段隐藏
    public string PublicProperty { get; private set; }
    
    // ✅ 好的实践:只读属性
    public DateTime CreatedTime { get; } = DateTime.Now;
    
    // ✅ 好的实践:抽象类定义契约
    public abstract class Validator
    {
        public abstract bool Validate(object obj);
    }
    
    // ✅ 好的实践:密封类防止滥用继承
    public sealed class ConcreteValidator : Validator
    {
        public override bool Validate(object obj) => obj != null;
    }
    
    // ❌ 不好的实践:过度使用public
    public string BadField;  // 应该用属性替代
    
    // ❌ 不好的实践:不必要的internal
    private void ShouldBePrivate() { }  // internal不必要
    
    // ❌ 不好的实践:滥用new隐藏成员
    public class BadDerived : BaseClass
    {
        public new void Method() { }  // 容易引起混淆
    }
}

五、快速参考卡片

访问修饰符速查

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    访问修饰符决策树                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  需要对外部程序集公开?                                       │
│      ├─ 是 → public                                          │
│      └─ 否 → 继续                                           │
│              ↓                                                │
│  需要派生类访问?                                            │
│      ├─ 是 → 继续                                           │
│      │       ↓                                                │
│      │   需要同一程序集访问?                                │
│      │       ├─ 是 → protected internal                      │
│      │       └─ 否 → protected                               │
│      └─ 否 → 继续                                           │
│              ↓                                                │
│  需要同一程序集访问?                                        │
│      ├─ 是 → 继续                                           │
│      │       ↓                                                │
│      │   需要派生类访问?                                    │
│      │       ├─ 是 → private protected                       │
│      │       └─ 否 → internal                                │
│      └─ 否 → private                                         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

类修饰符速查

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    类修饰符决策树                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  是否需要实例化?                                            │
│      ├─ 否 → static                                          │
│      └─ 是 → 继续                                           │
│              ↓                                                │
│  是否包含未实现成员?                                        │
│      ├─ 是 → abstract                                        │
│      └─ 否 → 继续                                           │
│              ↓                                                │
│  是否允许被继承?                                            │
│      ├─ 否 → sealed                                          │
│      └─ 是 → 普通类                                          │
│                                                              │
│  是否需要拆分到多个文件?                                    │
│      └─ 是 → partial                                         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

六、常见问题与陷阱

Q1: 为什么不能继承密封类?

A: 密封类表示这是最终实现,防止进一步扩展。通常用于:

  • 安全敏感的类(如密码处理)
  • 性能关键的类(避免虚方法调用)
  • 单例模式实现

Q2: abstract和virtual的区别?

csharp 复制代码
public abstract class Example
{
    // abstract: 必须由派生类实现,不能有方法体
    public abstract void MustImplement();
    
    // virtual: 提供默认实现,派生类可选重写
    public virtual void CanOverride() 
    {
        Console.WriteLine("默认实现");
    }
}

Q3: new和override的区别?

csharp 复制代码
public class Base { public virtual void Method() { } }
public class Derived : Base
{
    // new: 隐藏基类方法(编译时绑定)
    public new void Method() { }
    
    // override: 重写基类方法(运行时绑定)
    public override void Method() { }
}

Q4: 为什么不能在类内部定义protected internal成员?

A : 可以定义,protected internal 是有效的组合,表示"程序集内或派生类可访问"。


总结

  1. 访问修饰符 控制可见性,遵循最小权限原则
  2. 类修饰符控制行为特性,合理选择可提高代码质量
  3. 组合使用修饰符可以实现更精细的控制
  4. 实际项目中根据架构分层选择合适的修饰符组合

掌握这些修饰符的正确使用,是编写高质量、可维护C#代码的基础。

相关推荐
遨游建站2 小时前
谷歌SEO之网站内部优化策略
前端·搜索引擎
华洛2 小时前
聊聊我逃离前端开发前的思考
前端·javascript·vue.js
小码哥_常2 小时前
解锁Android权限申请新姿势:与前置说明弹窗共舞
前端
早點睡3902 小时前
ReactNative项目OpenHarmony三方库集成实战:react-native-gifted-charts
javascript·react native·react.js
星夜泊客2 小时前
C# : 引用类型都存在堆上吗
unity·c#
紫_龙2 小时前
最新版vue3+TypeScript开发入门到实战教程之路由详解三
前端·javascript·typescript
-SOLO-2 小时前
使用Cursor操控正在打开的Chrome
前端·chrome
chiwei_hua2 小时前
如何在 Blazor Web 前端中使用 C# 进行数据交互?
前端·c#·交互
pacong2 小时前
vscode使用
javascript·vue.js·vscode