c#中override virtual static abstract sealed 的作用

本文深入探讨了C#中静态与虚拟方法的概念,包括它们的定义、区别、使用场景以及如何在类中声明和覆盖这些方法。通过具体的代码示例,详细解释了静态方法和虚拟方法在类继承中的应用,以及如何实现多态性。此外,文章还阐述了静态方法、虚拟方法、抽象方法和密封方法之间的区别和联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

说明1:

表示静态的关键字
说明此对象在应用中只存在一份 

说明2:

C# 是面向对象的程序设计语言,每一个函数都属于一个类。

当一个方法被声明为Static时,这个方法是一个静态方法,编译器会在编译时保留这个方法的实现。也就是说,这个方法属于类,但是不属于任何成员,不管这个类的实例是否存在,它们都会存在。就像入口函数Static void Main,因为它是静态函数,所以可以直接被调用。

当一个方法被声明为Virtual时,它是一个虚拟方法,直到你使用ClassName variable = new ClassName();声明一个类的实例之前,它都不存在于真实的内存空间中。这个关键字在类的继承中非常常用,用来提供类方法的多态性支持。

例如,有一个类Test,Test类拥有两个方法Hello()和greet():
public class test
{
public void Hello()
{
System.Console.WriteLine("hello, world!");
}
.....
}
类TestMe派生自类Test,那么当你使用如下的代码:
Test a = new TestMe();
创建一个TestMe类的新实例后,假如你试图执行如下的代码:
a.Hello();
那么,自然就会运行基类Test的Hello()方法,但是如果你想给予派生类TestMe一个它自己的Hello()方法,你就要在Test类中将Hello()方法声明为虚拟的:
public virtual void Hello()
{
...
}
然后在派生类中以 override关键字表示覆盖基类的方法:
public class TestMe : Test
{
...

public overrice void Hello()
{
System.Console.WriteLine("hello from TestMe class!!!");
}

....
}
这时调用a.Hello(),就会出现“hello from TestMe class!!!”字样,而不是“Hello,world!”说明基类的方法已经被覆盖了。这就是多态性的表现。

从上面不难看出,一个静态的方法是真实存在的,而一个虚拟方法可以被派生类重写,这二者是冲突的,其实对于一个方法,C#规定只能使用下面这些限定符中的一个:
override virtual static abstract sealed
代表的含义分别为:
重载函 数、虚拟函数、静态函数、抽象函数、密封函数(不可派生)

另外,C#中定义一个方法的声明为:

可见性 类型 返回值 方法名(参数列表){方法体}

例如
public static void Test(int a){System.Console.WriteLine(a.ToString());}

这是一个公有的静态函数,函数名为Test,无返回值,有一个整形参数a,作用是把a的值输出在屏幕上。

 

说明3:

比如有类
class a
{
static void function1()
{}
}
和类
class b
{
b()
{}
void function2()
{}
}
如果要使用function1的时候,直接使用类名a.function1()就可以了,如果要使用function2()的话需要对b进行构建一个对象 也就是:b haha = new b(),然后haha.function2(),可以这样进行使用,
也就是说对于static修饰过的方法或者属性,对于所有的该类的对象都只有相同的一个,而没有修饰过的则表示,对于不同的对象,会有不同的属性,比如不同的人有不同的名字,身高等。

说明4:

public static 最好一个人开车
public 可以很多人一起开车

 

 

 

===========================

 

 

 

new 与 override的区别

 引用AnyTao博客中的一句话:
覆写(override)与重载(overload),是成就.NET面向对象多态特性的基本技术之一
正 如某网友说的那一句话:
Override 覆写 就是把原来的换掉了
new        新的 就是两个共存着

使用override重写xx方法,通过父类引用一样只能看到重写后的方法;
如 果使用new隐藏xx方法,父类子类引用各自对应方法;

override重写虚方法,那么就只剩下重写以后的方法;
new隐藏基 类的方法,那么基类的方法和当前类的方法同时存在只是被隐藏了;

 

 

使用override修饰符主要用来修改方法、属性、索引器或事件。重写基方法必须与重写方法具有相同的名称。
        不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
       重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。例如:虚方法为public的,重新方法也必须是public的。
        不能使用下列修饰符修改重写方法:
        new        static        virtual        abstract

        重写属性声明必须指写与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或是重写的。

要求:(三相同)
1、方法名称相同
2、参数列表相同
3、 返回值类型相同
一句话,只需要重新写方法内部的内容!

,override可以覆盖基类的方法,让基类的方法 以子类的内容实现,而new不用来覆盖基类的方法,而是全新定义一个子类的方法,这个方法只属于子类,与基类的方法无关,只是名字上相同而已

 


 

先看abstract和override使用方法

abstract class Base

    {

       public virtual void work()

        {

           MessageBox.Show("基类--开始工作");

        }

       public virtual void outwork()

        {

           MessageBox.Show("基类--下班");

        }

        

        Public abstract void Pay();      //声明抽象方法,必须要被子类new 或 override;只有当类是abstract时才可以声明abstract方法    

    }

   class Employee : Base

    {

       public new void work()

        {

           MessageBox.Show("子类(new)--开始工作");

        }

       public override void outwork()   //覆写抽象方法(一定要在子类覆写父类的抽象方法)

        {

            MessageBox.Show("子类(override)下班");

        }

              

//测试代码

        

c中override virtual static abstract sealed 的作用及代码分析 - 蒾亽迗哋 - 、Welcomes Space|゛c中override virtual static abstract sealed 的作用及代码分析 - 蒾亽迗哋 - 、Welcomes Space|゛Code
          //第一种情况
            Employee emp = new Employee();

            emp.work();              
//子类(new)--开始工作


            emp.outwork();          
//子类(override)下班     

            
//第二种情况

            Employee emp = new Employee();

            Base 
= (Base)emp;   
//指向抽象类了

            b.work();                
//基类--开始工作

            b.outwork();             
//子类(override)下班   被子类覆写了,所以不是显示基类下班

            
//第三种情况

            Base = new Employee();

            
//同上面是一样的


            b.work();                
//基类--开始工作

            b.outwork();             
//子类(override)下班

            Console.ReadLine();

   

new声明的方法,当使用子类的类型来调用的时候,它会运行子类中的函数,而如果类型是基类的话,被隐藏的基类函数就会站到前台来。只有使用virtual定义基类中的函数,并使用override标记子类中的函数,才可以达到想要的多态类(始终调用子类的方法)。

在子类中new父类中的方法,父类中的方法不一定是虚类型,即virtual

但是在子类中override父类中的方法,父类的方法一定得是虚类型,

 

代码示 例:

   abstract class Animal

    {

       public abstract void Drink();

       public abstract void GotoBed();

    }

   class Dog : Animal

    {

        publicoverride void Drink()

        {

           MessageBox.Show("小狗喝水");

        }

       public override void GotoBed()

        {

           MessageBox.Show("小狗睡觉");

        }

       public override string ToString()   //也可:public new string ToString()

        {

           return "小狗";

        }

    }

总结:

1、               抽象方法,必须要被子 override;只有当类是abstract时才可以声明abstract方法  

2、               因为abstract方法没有方法实现,其子类只能对其 abstract方法进行override,不能new(如果可以new的话,那么类的类型是父类的话,类的方法执行的是父类的方法而非子类的方法,而父类的方法却没有方法实现,那么将如何执行呢?)

3     Selaed方法必须与 override连用,也就是说实现sealed方法的类的父类必须实现了此方法(sealed关键字有两个作用:1,密封类不能被继承。2:密封方法重写基类中的方法,但其本身不能在任何派生类中进一步重写,Selaed方法必须与override连用

 

 

如下,A声明了virtual方法A1,那么 A的子类AA才能对Pay进行密封重写,AA的子类不能对A1重写或覆盖。

sealed方法的使用代码示例:

   class A

    {

       public virtual void A1()

        {

           MessageBox.Show("A---A1");   

        }

    }

   class AA:A

    {

       public sealed override void A1()

        {

           MessageBox.Show("AA---A1");

              

    }

总结

Public abstract void pay();                 abstract方法没有方法实现,必须继承

Public sealed override void pay(){}      sealed方法必须是重写父类的方法

Public static void pay(){}                   static方法通过类名访问

Public virtual void pay(){}                  virtual方法子类可以对其overridenew

Public new void pay(){}                     父类的方法pay不一定是virtual

Public override void pay(){}               父类的方法pay一定要是virtual

 

 

 

new、abstract、virtual、 override关键字的使用代码示例

 

public abstract class People   //abstract 说明类People是一个抽象类,不能被实例的
    {
        
public
 People()
        {
        }

        
public void
 Work()
        {
            MessageBox.Show(
"开始工作!"
);
        }

        
public virtual void GetOffWork()   //虚函数,说明此方法可以被子类覆盖(override)

        {
            MessageBox.Show(
"下班啦!"
);
        
    

    
public class Manage:People   //继承Popele 类

    {
        
public
 Manage()
        {
        

        
new public void Work()   //因为基类已经实现了Work方法,而在子类中又实现了Work方法,                                         //所以编译器会报警,在前面加上 new(隐藏基类方法),是将警报关闭。

        {
            
base.Work();   //
调用基类Popele的方法。显示“开始工作”
            
//MessageBox.Show("管理员开始工作罗!");

        

        
public override void GetOffWork()      //覆盖基类的方法

        {
            MessageBox.Show(
"管理员下班啦"
);
        
    }

    
public class
 Employee():People
    {
       
public
 Employee()
       {}

        
new public void GetOffWork()      //virtual方法仍然可以 new,abstract方法不能用new

        {
            MessageBox.Show(
"职员下班啦!"
);
        

    }

以上应该应该 几点:
1
、如果父类方法没有加virtual关键字,即不是一个虚方法,则在子类中只能隐藏基类方法,而不能覆盖。
2
、如果父类方法加了virtual关键字,即它是一个虚方法,在子类中一样可以隐藏。
3
、如果子类实现了父类相同的方法(相同的方法名称及签名),而没有new,在编译时会报警,但编译仍然能够通过!
3、调用父类方法:base
.方法名()
4、abstract类 是一个抽象类,不能被实例化
<think>嗯,用户这次的问题是关于C#sealed关键字的含义和用途。从对话历史看,用户之前询问过堆栈和堆的区别,现在转向了C#语言特性,可能是正在学习内存管理后转向面向对象编程的内容。用户提供的三个引用中,[1]和[2]是较口语化的介绍,[3]给出了具体代码示例。需要整合这些信息,但要注意[1]中提到的性能优化需要谨慎处理——实际上sealed对性能的影响很有限,主要用途还是设计层面的约束。用户明确要求理解"作用和用途",所以回答要聚焦三点:1)基本定义2)具体使用场景3)实际价值。特别要注意引用[2]提到this关键字的提问是干扰信息,需忽略。考虑到用户刚接触这个概念,解释时要避免术语轰炸。比如"虚方法表"这样的底层细节可以简化为"编译器优化机会"。代码示例选继承和重写两个典型场景就够,引用[3]的类密封例子正好适用。上次回答堆栈问题时用户接受了较专业的数学表达,但这次主题更偏设计模式,应减少公式使用。不过提到JIT优化时可以用$O(1)$简单说明常量时间优化。用户可能存在的潜在疑问:为什么需要禁止继承?所以要在使用场景部分强调框架设计和安全性需求。另外要提醒过度使用的风险,避免用户产生"所有类都该密封"的误解。</think>在 C# 中,`sealed` 关键字用于限制类或成员的继承和重写行为,其主要作用和核心使用场景如下: --- ### 一、`sealed` 的作用 #### 1. **密封类(Sealed Class)** - **作用**:阻止其他类继承该类。 - **语法**: ```csharp sealed class MyBaseClass { // 类成员 } ``` - **效果**:若尝试继承 `MyBaseClass`,编译器会报错: ```csharp class DerivedClass : MyBaseClass { } // ❌ 错误:无法从密封类继承 ``` #### 2. **密封方法/属性(Sealed Member)** - **作用**:在派生类中禁止重写已被 `override` 的虚方法或属性。 - **语法**: ```csharp class BaseClass { public virtual void Show() { } // 虚方法 } class DerivedClass : BaseClass { public sealed override void Show() { } // 密封重写 } class SubClass : DerivedClass { public override void Show() { } // ❌ 错误:无法重写密封方法 } ``` --- ### 二、核心使用场景 #### 1. **保护设计完整性** - **场景**:当类包含敏感逻辑(如加密算法)或核心架构(如框架基类),需确保其行为不被子类修改[^3]。 - **示例**: ```csharp sealed class EncryptionService { public string Encrypt(string data) { /* 核心加密逻辑 */ } } ``` #### 2. **优化性能** - **原理**:密封类/方法告知编译器“无需为继承预留灵活性”,JIT 编译器可进行内联调用等优化[^1]。 - **性能对比**: | 类型 | 虚方法调用开销 | 可内联优化 | |------------|----------------|------------| | 普通虚方法 | 较高(查虚表) | ❌ | | `sealed`方法 | 低 | ✅ | #### 3. **防止误用** - **场景**:工具类(如 `MathUtils`)或静态辅助类,继承无意义且可能引入错误[^2]。 - **示例**: ```csharp public sealed class StringHelper { public static string TrimAll(string input) { /* ... */ } } ``` #### 4. **安全性控制** - **场景**:在派生链中锁定特定方法的行为(如支付流程中的 `ValidatePayment` 方法)[^2]。 --- ### 三、使用注意事项 1. **避免过度使用** 随意密封类会限制代码扩展性,仅应在明确需要时使用。 2. **与 `abstract` 的互斥性** `abstract` 类要求被继承,而 `sealed` 禁止继承,二者不能同时修饰同一类。 3. **密封方法的限制** 只能用于重写后的虚方法(即必须与 `override` 联用),不能直接修饰非虚方法。 --- ### 四、实际应用示例 ```csharp // 密封类:禁止继承 sealed class Logger { public void Log(string message) => Console.WriteLine(message); } // 密封方法:禁止进一步重写 class Shape { public virtual void Draw() => Console.WriteLine("绘制形状"); } class Circle : Shape { public sealed override void Draw() => Console.WriteLine("绘制圆形"); } class RedCircle : Circle { // 以下代码报错:无法重写密封方法 // public override void Draw() { } } ``` > **关键总结**:`sealed` 是 C# 中的“封印”机制,用于保护类不被继承或方法不被重写,适用于安全性、性能优化和设计约束场景[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值