C#事件(基础)

C# 事件(Event)详解 定义委托类型:声明事件的委托类型。定义事件:使用event关键字声明事件。触发事件:通过委托触发事件。//声明委托类型//声明事件//触发事件的方法MyEvent?");//触发事件//事件处理方法//订阅事件//触发事件• 事件是基于委托的,提供了一个更严格的方式来管理方法的调用,尤其适用于需要通知和异步操作的场景。• 事件允许发布-订阅模式,使得多个对象能够订阅并响应特定的事件。 阅读详情

前言:

通过上文(C#委托)的学习我们了解了委托的基本用法,而事件是建立在委托的基础之上的。
在了解事件之前我们要先知道一个设计模式:发布者订阅者模式

发布者订阅者模式

比如说,你订阅了某个作者,那么订阅的作者发布的文章,会广播给每一个订阅者,此时订阅的作者就是发布者(Publisher),你和每个订阅者就是订阅者(Subscriber),你们收到的文章叫做Message。
发布/订阅模式在设计模式中属于行为型模式(Behavioral Patterns)
发布者不会将消息直接发送给特定的接收者,而是通过消息通道广播出去,让订阅过消息的订阅者收到。

这种模式松耦合,也就是发布者和订阅者各尽其职,而不是使他们连接在一起,但是由于中间需要代理,增加了系统的复杂度,发布者不知道发布的消息或文章是否被订阅者接收到,增加了不稳定性。
发布/订阅模式的应用场景:
1、程序需要向大量的消费者广播
2、应用程序可以向消费者发送信息,而不需要实时响应
3、应用程序需要与一个或多个独立开发的应用程序或服务通信,而这些应用程序或服务可能使用不同的平台、编程语言和通信协议。
4、被集成的系统被设计为支持其数据的最终一致性模型(关于最终一致性:https://www.cnblogs.com/siyuanwai/p/14302444.html)
5、应用程序需要将消息传递给多个消费者,这些消费者可能具有与发送者不同的可用性要求或正常运行时间计划。例如消息在早上发布出去,消费者计划在下午才去处理这些信息。

在了解完基本的设计模式之后,我们了解一些事件的重要概念:
发布者(publisher):发布某个事件的类或结构,其他类可以在该事件发生时得到通知。
订阅者(subscriber):注册并在事件发生时得到通知的类或结构
事件处理程序(event handler):由订阅者注册到事件的方法,在发布者触发事件时执行。其定义在事件所在的类或结构中,也可以定义在不同类或结构中。
触发事件(raise):调用(invoke)或触发(fire)事件的术语。当事件触发时,所有注册到它的方法都会被依次调用。

声明事件

class Incrementer
    {
        //在类中声明,需要委托类型的名称,
        //声明为public,这样就可以让其他类和结构在其上面注册事件处理程序
        //不能使用new关键字创建它的对象。
        public event EventHandler Counted;
        //EventHandler是事件委托,底层也是delegate,多被声明为event

        //声明多个事件
        public event EventHandler MyEvent1, MyEvent2, MyEvent3;

        //同时事件也可以声明为静态
        public static event EventHandler StaticEvent;

    }

事件和方法、属性一样,是类或结构的成员,同时注意:
不能在一段可执行代码中声明事件,必须声明在类或结构中。

订阅事件:

订阅者向事件添加事件处理程序。
使用+=来进行添加,事件处理程序位于+=的右面
事件处理程序的形态:实例方法的名称、静态方法的名称、匿名方法、Lambda
例如:

class Incrementer
    {
        public event EventHandler Counted;

        //触发事件函数
        public void DoCount()
        {
            Counted(null,null);
        }

    }

    

    class Program
    {
        static void staticCount(object? sender, EventArgs e)
        {
            Console.WriteLine("静态方法被调用");
        } 

        static void Main(string[] args)
        {

            Incrementer incrementer = new Incrementer();

            //添加静态方法
            incrementer.Counted += staticCount;
            //委托类型
            incrementer.Counted += new EventHandler(staticCount);
            //lambda
            incrementer.Counted += (object? sender, EventArgs e) => Console.WriteLine("lambda被调用");
            //匿名方法
            incrementer.Counted += delegate { Console.WriteLine("匿名方法被调用"); };

            //触发事件
            incrementer.DoCount();
        }
    }

输出

静态方法被调用
静态方法被调用
lambda被调用
匿名方法被调用

触发事件

事件成员本身只是保存了需要被调用的时间处理程序,如果时间没有被触发,什么都不会发生。
在发布者类中定义触发事件的代码:

if(DoCount!=null){
    DoCount(source,args);
}

DoCount:事件名
source,args:参数列表
在触发事件事前建议和null进行比较,从而查看是否包含事件处理程序,如果不包含(为null),则不执行
其中触发事件 的参数列表中必须与事件的委托类型相匹配。

举个简单的例子,我们先创建一个发布者类(Incrementer)和一个订阅者类(Dozens),
(这里回顾一下,订阅者负责订阅事件和声明事件处理程序,发布者创建事件并发布)
我们通过main函数创建发布者对象publisher,然后创建一个订阅者,声明事件处理程序并且订阅事件,然后触发事件,得到触发事件后的效果。

delegate void Handler();//声明的委托

class Incrementer
{//发布者
    //创建事件并发布
    public event Handler CountedDozen;
    //触发事件(调用事件)
    public void DoCount()
    {
        for (int i = 0; i < 10; i++)
        {//设置触发10次
            if (CountedDozen != null)
            {//如果事件不为空则触发事件一次
                CountedDozen();
            }
        }
        
    }
}
class Dozens
{//订阅者
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
        //订阅事件
        incrementer.CountedDozen += AddDozensCount;
    }
    //声明事件处理程序
    void AddDozensCount()
    {
        this.DozensCount++;
    }
}
class Class1
{
    static void Main()
    {
        Incrementer incrementer = new Incrementer();
        Dozens dozens = new Dozens(incrementer);
        incrementer.DoCount();
        Console.WriteLine($"DozensCount Value is {dozens.DozensCount}");
    }
}

输出:

DozensCount Value is 10

可以看到发布者在事件发生时触发了10次事件,所以自增10次,得到的结果是10.

标准事件

GUI编程是事件驱动的,在程序运行时,其可以在任何时候被事件打断,比如你按下按钮的时候,按下某个按键的时候。在这些情况发生时,程序需要处理完事件之后才能继续做其他事。
程序事件的异步处理是使用C#事件的最佳场景,对于事件,.NET提供了一个标准事件。在System命名空间下的EventHandler委托类型。

namespace System
{
    //
    // 摘要:
    //     Represents the method that will handle an event that has no event data.
    //	   表示将处理没有事件数据的事件的方法。
    // 参数:
    //   sender:
    //     The source of the event.事件的来源
    //
    //   e:
    //     An object that contains no event data.不包含事件数据的对象
    public delegate void EventHandler(object? sender, EventArgs e);
}

其中
第一个参数用来保存触发事件的对象的引用。
第二个参数用来保存状态信息,指明什么类型适用于该应用程序。
EvenArgs表示包含事件数据的类的基类,并提供用于不包含事件数据的事件的值。
EventArgs参数用于不需要传递数据的事件处理程序,如果需要传递数据,需要声明一个派生自EventArgs的类,使用合适的字段来保存需要传递的数据。
我们可以修改上面的例子代码,使其使用EventHandler类型的委托(一定要注意类型匹配):

class Incrementer
{//发布者
    //创建事件并发布
    public event EventHandler CountedDozen;
    //触发事件(调用事件)
    public void DoCount()
    {
        for (int i = 0; i < 10; i++)
        {//设置触发10次
            if (CountedDozen != null)
            {//如果事件不为空则触发事件一次
                CountedDozen(this,null);
            }
        }
    }
}
class Dozens
{//订阅者
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
        //订阅事件
        incrementer.CountedDozen += AddDozensCount;
    }
    //声明事件处理程序
	void AddDozensCount(object? sender, EventArgs e)
	{
        	this.DozensCount++;
    }
}
class Class1
{
    static void Main()
    {
        Incrementer incrementer = new Incrementer();
        Dozens dozens = new Dozens(incrementer);
        incrementer.DoCount();
        Console.WriteLine($"DozensCount Value is {dozens.DozensCount}");
    }
}

一共改了四处,第一处删除了之前声明的委托类型,第二处修改了声明事件处理程序的参数,第三处和第四处修改了发布者中的创建时间类型,以及触发事件传入的参数。

EventArgs传参

自定义类:

public class IncrementerEventArgs : EventArgs
{
    public int IterationCount { set; get; }//存储整数
}

IncrementerEventArgs 是我们自定义的类
EventArgs是我们的基类
继承了EventArgs之后我们就可以对事件处理程序的第二个参数传递数据,我们需要用到泛型的委托(EventArgs<>)来获得该类:

public event EventHandler<IncrementerEventArgs> CountedADozen;

CountedADozen是我们声明的事件名称
EventHandler代表泛型委托使用我们自定义的类(IncrementerEventArgs)
我们在上面的代码中加入我们自定义的类型试试:

public class IncrementerEventArgs : EventArgs
{
    public int IterationCount { set; get; }//存储整数
}
class Incrementer
{//发布者
    //创建事件并发布
    //使用自定义类的泛型委托
    public event EventHandler<IncrementerEventArgs> CountedDozen;
    //触发事件(调用事件)
    public void DoCount()
    {
        //自定义类的对象
        IncrementerEventArgs args = new IncrementerEventArgs();
        for (int i = 0; i < 10; i++)
        {//设置触发10次
            if (CountedDozen != null)
            {//如果事件不为空则触发事件一次
                args.IterationCount = i;
                //触发时传递我们自定义类对象的参数
                CountedDozen(this,args);
            }
        }
    }
}
class Dozens
{//订阅者
    public int DozensCount { get; private set; }
    public Dozens(Incrementer incrementer)
    {
        DozensCount = 0;
            //订阅事件
            incrementer.CountedDozen += AddDozensCount;
    }
    //声明事件处理程序
    void AddDozensCount(object? sender, IncrementerEventArgs e)
    {
        Console.WriteLine($"this is {e.IterationCount} in {sender.ToString()}");
        this.DozensCount++;
    }
}
class Class1
{
    static void Main()
    {
        Incrementer incrementer = new Incrementer();
        Dozens dozens = new Dozens(incrementer);
        incrementer.DoCount();
        Console.WriteLine($"DozensCount Value is {dozens.DozensCount}");
    }
}

输出:

this is 0 in EventStu.Incrementer
this is 1 in EventStu.Incrementer
this is 2 in EventStu.Incrementer
this is 3 in EventStu.Incrementer
this is 4 in EventStu.Incrementer
this is 5 in EventStu.Incrementer
this is 6 in EventStu.Incrementer
this is 7 in EventStu.Incrementer
this is 8 in EventStu.Incrementer
this is 9 in EventStu.Incrementer
DozensCount Value is 10

移除事件处理程序

这个没啥说的,就是在用完了事件处理程序之后,把其从事件中移除,我们可以使用-=把其从事件中移除。
同时与委托相同,如果一个处理程序向事件注册了多次,那么执行移除处理程序时,只移除该处理程序中的最后一个实例

事件访问器

+= 和-=是事件中允许 的唯一运算符,但是这些运算符可以进行预定义行为,也就是说我们可以修改这些运算符的行为,使用他们时可以让事件执行任何我们希望执行的自定义代码。
改变这两个运算符的操作就需要事件定义事件访问器
其中有两个访问器:add和remove,声明访问器的方式与声明属性类似。

public event EventHandler CountedADozen
{
    add
    {
        //执行+=运算符的代码
    }
    remove
    {
        //执行-=运算符的代码
    }
}

声明事件访问器之后,事件不包含任何内嵌委托对象。我们必须实现自己的机制来存储和移除事件注册的方法。
注意:事件访问器中为void方法
两个访问器都含有名称为value的隐式值参数,可以接收实例或静态方法的引用,
就是像文档中这样直接使用value隐式值参数:

event EventHandler IDrawingObject.OnDraw
{
    add
    {
        lock (objectLock)
        {
            PreDrawEvent += value;
        }
    }
    remove
    {
        lock (objectLock)
        {
            PreDrawEvent -= value;
        }
    }
}

总之,事件就是对象之间通信的一种机制,任何一个对象都可以有其对应的事件

C#事件实例详解 通过实例说明事件的定义、使用。并说明相关意义和使用技术及原因。 阅读详情

相关推荐

C# 事件机制详解:定义、订阅、触发与应用实践

C# 中声明事件使用event关键字。事件依赖于委托类型,所以我们首先需要定义一个合适的委托类型来指定事件的签名。常见的事件委托类型有和。通过定义自定义的事件参数,可以传递更多的数据,丰富事件的功能。例如,通知文件的上传进度、数据的加载状态等。C# 中的事件机制是基于委托的强大功能,广泛用于处理对象之间的通知和消息传递。事件机制遵循发布-订阅模式,允许开发者在松散耦合的情况下,进行灵活的通信和响应。通过事件,我们可以轻松地实现异步编程、UI 响应、状态更新等功能,提升程序的可扩展性和可维护性。

net core ,前端 ,python 全栈开发 1472

【C#进阶】C# 事件

🌍 hello大家好啊,我是哈桑。本文为大家介绍 C# 中的事件。事件本质上来讲是一种特殊的多播委托1,只能从声明它的类中进行调用。事件通常用于表示用户操作,例如单击按钮或图形用户界面中的菜单选项。C# 中常常会使用事件来实现线程之间的通信。不仅是在类中,在接口中也可以声明事件,称为接口事件。接口事件的实现和接口上的方法或属性的实现是一样的,以一个示例来说明如何在类中实现接口事件。

好学若饥,谦卑若愚。 5302

Unity C#基础:委托与事件

在面试中,委托与事件几乎是必问的。如果面试官和面试者互不相识,面试官不问委托,那我严重怀疑这家公司的技术水平,这个可以说是C#入门与掌握的分水岭之一,非常重要。所以,这里我整理一片笔记,对委托和事件做一个全面的整理和归纳。这里重在理解,只有理解了才能真正掌握它。 目录 目录 1. 为什么C#会有委托事件? 2.观察者模式的缺陷: 3.为什么要费这么大劲? 1. 为...

q493201681的博客 1万+

C#事件--全网最全+全网最易理解

一、初步了解事件 1.事件的定义: 事件英文解释为:a thing that happens,especially something important.

nameyichao的博客 3万+

C#基础——代理和事件

代理和事件 事件 所谓事件就是由某个对象某个对象发出的消息。例如按下某个按钮,某个文件发生了变化。触发事件的对象叫做sender,捕获事件并且作出相应的对象叫做receiver,一个事件可以有多个receiver C#代理 代理(delegate)是C#中的一种类型,是一个能够持有对某个方法的引用的类。delegate拥有一个签名(signature),且只能持有与其它的签名相匹配的方法的引用。d...

Aaron's Coding Life 1394

C#基础学习_事件与委托

C#基础学习_事件与委托

Robot_PLC_HMI_Automation 383

C#基础知识点 事件

为了避免发布者生命周期长于订阅者,订阅者被销毁时未取消订阅,订阅者无法被垃圾回收等情况引发的内存泄漏问题,通过实现IDisposable接口规范化,确保订阅者销毁时自动取消事件订阅。同样, 大部分内容主要是来自于C#图解教程 教材书中,读到这的同学也可以查看书籍进行系统性的学习,这里只能梳理个人的知识架构。函数成员包括方法,属性,构造函数,析构函数,事件,运算符和索引。委托调用的方式有两种,使用调用方法的方式调用,另一种是使用委托的invoke方法。这里涉及到接口的概念,写到接口部分的时候再补充。

weixin_49155681的博客 405

InSAR图像配准:从像素级到亚像素级的精度提升策略

本文深入探讨了InSAR图像配准技术,从像素级到亚像素级的精度提升策略。通过分析最大频谱法和相干系数法的适用场景,结合频域补零插值和四叉树分块等高级技术,实现1/8像素级的高精度配准。文章还提供了实用的精度验证方法和常见问题排查指南,为InSAR数据处理提供全面解决方案。

nginx7reverse的博客 836

C#-winform基础-事件弹窗

1.winform应用程序是一种智能客户端技术,我们可以使用winform应用程序。 帮助我们获得信息或者传输信息等。 实用简单控件介绍: 属性 name:在后台要获得前台的控件对象,需要使用name属性 visible:指示一个控件是否可用。 Enabled:指示一个控件是否可用。 事件 注册事件: 触发事件: 一般如按钮之类的我就不介绍了 ContextMenuStrip:右键菜单栏拖进界面 绑定你需要的控件就可以 绑定方法如图: 我綁定了界面,所以右击界面都会弹出右键菜单功能 ...

opinion001的博客 8348

基于Java的高校学生信息管理系统的设计与实现(论文+源码)

可以对本系统的数据进行良好的封装,Java可以对不想被访问的数据进行良好的隐藏,具备平台无关性,可移植,更加可靠与安全,具备多线程支持,进行网络交互更容易。它支持本系统的B/S模式。开发效益方面,本系统一旦开发成功并且面向社会,就会让大多数的学生教师体会到便利办公的乐趣,随之促进提高本系统的使用率和经济利润,所以在经济方面,对于零成本开发且高利润的学生管理系统是可行的。学生可以在学生端进行选课,查看自己的成绩,教师可以在教师端查看所任课程的选课情况,对学生成绩进行录入,对所任的课程进行结课等操作。

2402_82389843的博客 1092

基于SolidWorks宏的草图点坐标自动化提取与Excel集成

本文详细介绍了如何利用SolidWorks宏编程实现草图点坐标的自动化提取并与Excel集成,显著提升机械设计效率。通过VBA代码解析与优化,解决了人工记录坐标耗时易错的问题,并扩展了多草图批量处理、数据可视化等高级功能,适用于数控加工、质量检测等场景。

weixin_29251131的博客 461

C#零基础学习之事件

C#零基础学习之路——事件 一. 学习背景 基于学习b站刘老师的c#入门,整理学习心得。 二. 事件 2.1 什么是事件 能够发生的事情 2.2 事件模型 1.事件的拥有者(类或者对象) 2.事件(成员) 3.事件的响应者(类或者对象) 4.事件处理器(事件响应者的方法成员) 5.事件订阅:把事件处理器与事件关联起来,本质上是一种以委托类型为基础的约定。 补充: 1.挂接事件处理器的时候,可以使用委托实例,也可以使用方法名,这是"语法糖"。 2.事件处理器对事件的订阅不是随意的,匹配与否由声明事件时所使用的

wangyuyu0000的博客 281

手把手教你用神经网络优化电机控制:从Simulink仿真到实际部署

本文提供了一套完整的工程实践指南,详细讲解了如何将神经网络应用于电机控制,从Simulink仿真建模、轻量级网络设计,到关键的模型量化与代码生成,最终实现向DSP/FPGA硬件的实际部署。文章直面实时性、精度与资源限制等核心工程挑战,为工程师提供了从理论到落地的清晰路径和实用避坑策略。

weixin_29246195的博客 226

C#基础之委托,事件

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自类。C# 事件(Event)是一种成员,用于将特定的事件通知发送给订阅者。事件通常用于实现观察者模式,它允许一个对象将状态的变化通知其他对象,而不需要知道这些对象的细节。事件(Event。

上善若泪 2732

如何卸载Gazebo与重装

gazebo是一款关于车辆和无人机的仿真软件,本文大致介绍它是何物,以及他的安装和卸载方法,对于ROS开发者,本文有一定参考意义。

gongdiwudu的专栏 1万+

FT2004(D2000)开发实战之网口stmmac报错调试(Failed to reset the dma)

网口stmmac报错调试(Failed to reset the dma)

嵌入式Linux 3584

C#中的委托与事件笔记——基础

学习笔记内容来自B站UP主十月的寒流,内容仅作学习记录

WDaMu的博客 795

从4A架构的角度出来 帮我分析一下:数字化转型深水区:企业架构如何成为价值重构的核心引擎?

4A 架构的本质是构建企业的数字神经系统,通过业务感知、数据传输、决策执行、技术支撑的闭环,实现从效率提升到生态重构的质变。正如华为通过该架构实现全球研发资源统一调度,某零售集团借此打造线上线下融合的新零售体系,当业务、数据、应用、技术四个维度形成共振时,企业将获得持续进化的数字免疫力,在不确定的市场环境中保持韧性生长。这一过程不仅需要技术工具的升级,更依赖组织文化的变革 —— 从 “部门墙” 到 “能力网” 的转型,才是数字化转型深水区的终极挑战。

金牌架构师 1046

C#基础之事件(1)

事件是C#语言的重要成员之一,初学者往往不能很好的去理解和运用事件,特别是自定义事件。在这里将以较简单的方式呈现事件最基本的用法。 1.事件的定义 给事件下个准确的定义是一个较困难的事,这里我暂且给它定义为:事件是两个对象之间的交互行为,这里关注四个字“两个对象”。不理解不要紧,这样定义本身并不准确。,继续往下看。 事件定义之前先声明一个委托,然后声明一个事件: //声明委...

aiga1990的博客 149

【AI智能体】Codex 开发聚合搜索应用项目实战操作详解

Codex 开发聚合搜索应用项目实战操作详解

congge 3096

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【c#基础】事件

本章主要记录如何使用事件。【参考文章】《c# 图解教程》(第五版)

xucoco1的博客 243

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C# 事件的基础

using System; using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { BoiledEventArgs boil =

q510264505的博客 352

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C#基础概念之事件

事件,是C#编程模型中重要的一个概念,通过对事件的理解,可以更好的了解C#程序运行机制。C#中的事件,可以简单的理解为类或者对象发生了一件事,并且把这件事通知给了其他的类或者对象,其他的类或者对象可以根据事件的消息有所反应。这非常类似设计模式中的观察者模式。

杨延成的专栏 363

C#基础-委托与事件

委托与事件是一堆相互关联的概念,委托是一种引用类型,可用于封闭命名方法或你们方法;事件可以使类或对象想其他类或对象通知发生的相关事情。因为灵活的事件处理要求将事件的相应分派给相应的事件处理方法,而C#中事件处理方法通常都是委托实现的。委托也可以用作回调,这样一个类可以告诉另一类:“执行这个操作,干完后通知我”。 using System; using System.Collections.Gen

THREEK的专栏 698

C#基础【十一】委托、事件、反射

文章目录一、委托二、事件三、反射 一、委托 C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。 委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。 引用可在运行时被改变。 委托(Delegate)特别用于实现事件和回调方法。 所有的委托(Delegate)都派生自 System.Delegate 类。 声明委托 委托声明决定了可由该委托引用的方法。 委托可指...

zyp_baoku的博客 474

C#基础——事件

事件具有以下特点: 1、发行者确定何时引发事件,订户确定执行何种操作来响应事件。 2、一个事件可以有多个订户,一个订户可处理来自多个发行者的多个事件。 3、没有订户的事件永远不会被调用。 4、事件通常用于通知用户操作。 5、如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。 6、可以利用事件同步线程 7...

weixin_30305735的博客 99
上一篇: C#委托(1基础)
下一篇: C#枚举器和迭代器
吊云
博客等级 码龄6年 73粉丝 10原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值