21天精通C#编程

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:《21天学C#》是一本针对初学者的全面C#编程指南,目的是在三周内帮助读者建立扎实的编程基础,并能够高效开发.NET平台软件。本书介绍了C#的创建背景、基本语法、面向对象特性和.NET框架的架构与组件,还涉及了*** Web应用开发。此外,书中还涵盖了一些高级主题如异常处理、委托、LINQ和异步编程,为读者提供了深入学习C#的机会。本书适合希望提升C#技能的程序员和新手开发者。

1. C#语言概述与环境配置

1.1 C#语言的起源和发展

C#(发音为 "C Sharp")是由微软公司开发的一种现代、类型安全的面向对象编程语言。它始于1999年,作为.NET框架的一部分被引入,C#的设计目标是结合C++的高性能和Visual Basic的快速开发能力。C#在语言设计上受到了Java的启发,但它也引入了自己独特的特性,比如属性、委托和匿名方法。随着C#版本的不断更新,如今的C#已经成为一种功能强大、表达能力丰富的语言,适用于企业级开发、游戏开发和移动应用等多种场景。

1.2 C#环境配置

要开始C#开发,首先需要一个合适的开发环境。推荐使用Visual Studio IDE,它是微软提供的一个综合性的开发环境,支持C#等多种编程语言。从Visual Studio的官方网站下载并安装Visual Studio Community版即可开始免费使用。安装时确保选择了“.NET桌面开发”和“.NET Web开发”工作负载,这样就包含了C#开发所需的所有工具和组件。

1.3 创建第一个C#控制台应用程序

在环境配置完成后,接下来进行简单的实践以熟悉C#的开发流程。按照以下步骤创建第一个C#控制台应用程序:

  1. 打开Visual Studio。
  2. 选择“创建新项目”,在项目类型中选择“控制台应用(.NET Core)”或“.NET Framework”。
  3. 输入项目名称,并选择一个合适的位置存储项目文件,然后点击“创建”。
  4. Visual Studio会生成一个基本的控制台应用程序模板,其中包含一个名为 Program.cs 的文件。
  5. Program.cs 文件中的 Main 方法中输入代码 Console.WriteLine("Hello, World!");
  6. 保存文件并点击“开始调试”或按F5键运行程序,控制台窗口会显示消息“Hello, World!”。

通过这个简单的例子,你已经完成了C#的环境搭建并成功运行了你的第一个程序,这标志着你作为C#开发者的起始旅程。接下来的章节将进一步深入C#的语法和高级特性,为成为专业C#开发人员打下坚实的基础。

2. C#基础语法与面向对象编程

2.1 C#基本语法元素

2.1.1 数据类型和变量

在C#中,数据类型可以分为两大类:值类型和引用类型。值类型变量直接存储数据,而引用类型变量存储对数据(对象)的引用。基本的值类型包括整型(int)、浮点型(float和double)、布尔型(bool)、字符型(char)和枚举(enum)。引用类型主要包括类(class)、接口(interface)、委托(delegate)和数组(array)。

为了使用变量,必须先声明变量并指定其类型。例如,声明一个整数变量的语法如下:

int number = 42;

这里, int 是变量的数据类型, number 是变量名,而 42 是赋给变量的初始值。C# 还支持默认值初始化,例如:

int defaultNumber; // 默认值为0
bool isCompleted = false; // 默认值为false

2.1.2 控制结构和循环语句

控制结构用于基于条件或重复执行代码块。C# 提供了 if-else switch 语句用于条件控制,以及 while do-while for foreach 用于循环结构。

下面是一个 if-else 语句的示例:

int number = 10;

if (number > 0)
{
    Console.WriteLine("Number is positive.");
}
else if (number < 0)
{
    Console.WriteLine("Number is negative.");
}
else
{
    Console.WriteLine("Number is zero.");
}

循环语句允许我们执行重复的任务。例如,使用 for 循环打印从1到10的数字:

for (int i = 1; i <= 10; i++)
{
    Console.WriteLine(i);
}

每个控制结构和循环语句都有其特定的使用场景。开发者应根据实际需求选择合适的结构来编写清晰、高效的代码。

2.2 面向对象编程的原理与实现

2.2.1 类与对象的概念

类是面向对象编程(OOP)中的基本构造块,是创建对象的模板。类定义了一组数据和方法,数据描述对象的状态,方法定义对象的行为。对象是类的实例。

下面是一个简单的类定义:

public class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public void StartEngine()
    {
        Console.WriteLine("Engine started.");
    }
}

要创建并使用这个类的对象,可以如下:

Car myCar = new Car();
myCar.Make = "Toyota";
myCar.Model = "Corolla";
myCar.StartEngine();

2.2.2 封装、继承和多态性

封装是隐藏对象内部复杂性的机制。在C#中,封装是通过访问修饰符(如 public private )来实现的。

继承允许一个类(子类)继承另一个类(父类)的属性和方法。例如:

public class ElectricCar : Car
{
    public string BatteryType { get; set; }
}

多态性是允许使用父类类型的引用指向子类对象,并调用在不同子类中实现的方法。这是通过在类中实现接口或抽象类来实现的。

2.3 面向对象编程的高级特性

2.3.1 抽象类与接口

抽象类是不能实例化的类,它通常包含抽象方法,这些方法必须在派生类中实现。抽象类用 abstract 关键字声明。

public abstract class Vehicle
{
    public abstract void Start();
    public void Stop()
    {
        Console.WriteLine("Vehicle stopped.");
    }
}

接口定义了类应该实现的方法,但不提供方法的实现。接口是用 interface 关键字定义的。

public interface IStartable
{
    void Start();
}

类可以实现多个接口,但只能继承一个类。接口在定义了行为契约的同时允许类实现多种行为。

2.3.2 集合与泛型

集合是用于存储多个数据项的对象。C# 提供了各种集合类,如 List<T> Dictionary<TKey,TValue> 等。

泛型集合允许在定义集合类型时指定其元素的类型,这样就无需在运行时进行类型转换。例如:

List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");

泛型提供了一种高效且类型安全的方式来实现集合,使集合能够作为类型安全的容器处理不同的数据类型。

3. C#框架基础架构与组件

框架概述

框架的核心组件

C#作为.NET框架的核心语言,其架构与组件的设计充分体现了微软对开发效率与维护性的重视。框架中的核心组件涵盖了程序集、公共语言运行时(CLR)、基础类库等部分,每一个都为.NET应用程序的运行提供了必不可少的支持。

  1. 程序集 : 程序集是.NET应用程序的基本部署单元,可以包含可执行代码、资源以及元数据。程序集分为两种类型:应用程序程序集和动态程序集。程序集以DLL或EXE文件的形式存在,允许代码被轻松地重用,同时提供了版本控制和隔离功能。
  2. 公共语言运行时(CLR) : CLR是.NET框架的核心,它为代码的运行提供了环境。CLR负责代码的加载、执行以及内存管理。通过CLR,C#代码在执行前会被编译为中间语言(IL),并在运行时由JIT(Just-In-Time)编译器编译为机器码。

  3. 基础类库 : .NET框架包含了丰富的基础类库,提供了一系列预先编写好的类和接口,用于处理常见的编程任务,如字符串操作、文件I/O、网络编程等。基础类库使得开发者能够专注于业务逻辑的实现,而不需要从零开始编写底层代码。

程序集和版本控制

程序集的概念极大地提高了代码的可维护性和可重用性,而版本控制机制则确保了在同一个系统中可以存在多个版本的组件,而不相互冲突。这种机制对于库的维护和应用程序的更新尤为重要。

  1. 版本控制 : 程序集的版本控制通过其清单(Manifest)实现,该清单记录了程序集的版本号以及依赖的其他程序集的信息。版本号遵循主版本号.次版本号.修订号.构建号的格式,使得不同版本的程序集能够共存,并且可以在不影响其他程序的情况下进行升级。

  2. 强命名程序集 : 强命名的程序集包含了一个公钥/私钥签名,确保了名称的唯一性。这允许程序集在全局程序集缓存(GAC)中存储,并可以被多个应用程序共享。

  3. GAC : 全局程序集缓存(GAC)是一个机器范围的仓库,用于存放共享的、强命名的程序集。通过GAC,相同的程序集只有一个副本被存储和维护,从而节省了磁盘空间并提高了效率。

常用框架组件及其应用

和数据库交互

C#框架提供了多种与数据库交互的方式,其中最为常用的是***和Entity Framework。

  1. : 是一个构建数据访问服务的框架,提供了对关系型数据库的直接访问。它包括了DataSet, DataTable, DataAdapter等对象,这些对象允许对数据库执行查询、更新等操作。通过使用Connection, Command, DataReader等类,开发者可以执行SQL命令并处理结果集。

  2. Entity Framework (EF) : Entity Framework是一个对象关系映射(ORM)框架,它抽象了数据访问的复杂性,允许开发者通过操作对象来管理数据。Entity Framework支持Code First, Model First和Database First开发模式,提供了丰富的功能如延迟加载(Lazy Loading)、变更跟踪、事务处理等。

用于Web开发

是用于构建Web应用程序的框架,它支持多种开发模型,包括 MVC, *** Web Forms和*** Core。

  1. *** MVC**: MVC代表模型(Model)、视图(View)和控制器(Controller),它是一种分层的架构模式,用于将用户界面和业务逻辑分离。通过将应用程序分解为模型、视图和控制器,MVC模式提高了代码的可维护性和测试性。

  2. *** Core : *** Core是一个跨平台、模块化的.NET框架,用于构建现代Web应用。它提供了一套精简的核心框架,可以在多种操作系统上运行,如Windows, Linux和macOS。 * Core具有更好的性能,并且更加轻量级,它还支持依赖注入和服务的配置。

高级组件和应用场景

Windows Forms和WPF

Windows Forms和WPF(Windows Presentation Foundation)是C#中用于创建桌面应用程序的两个主要框架。

  1. Windows Forms : Windows Forms提供了一种简单的方法来创建图形用户界面(GUI)。它基于控件的概念,开发者可以通过拖放控件的方式来创建表单。尽管较之WPF较为老旧,但Windows Forms依然因其简单性和高效性在某些特定应用场景中被广泛使用。

  2. WPF : WPF是一种现代化的UI框架,提供了一种声明式的编程方式,允许开发者使用XAML(一种基于XML的标记语言)来设计用户界面。WPF支持复杂的动画、3D图形、绘图以及丰富的视觉效果,非常适合创建复杂的桌面应用程序。

LINQ和Entity Framework

LINQ(语言集成查询)和Entity Framework是C#中处理数据查询的强大工具。

  1. LINQ : LINQ是.NET框架中集成的数据查询语法,它允许开发者使用C#进行声明式数据查询。通过LINQ,开发者可以在对象集合、数据库、XML文档等多种数据源中以统一的方式进行查询。

  2. Entity Framework : 作为高级ORM框架,Entity Framework内置了对LINQ的支持,使得从数据库查询数据变得异常简单。开发者可以使用LINQ to Entities来构建查询,并通过Entity Framework将其转换为数据库特定的查询语句。

通过本章节的介绍,我们可以看到,C#框架不仅提供了构建基础应用程序的工具,还通过其高级组件支持了更多复杂的应用场景。无论是桌面应用程序的开发,还是Web应用的构建,C#框架都提供了丰富且强大的组件与接口,使得开发者可以高效地实现需求。

4. C#高级编程主题

4.1 异常处理机制

4.1.1 异常类型与异常捕获

在C#中,异常处理是确保应用程序能够稳定运行的关键。异常通常是指程序运行时发生的不正常情况。C#提供了一套强大的异常处理机制,用于处理运行时错误和异常情况。

异常处理通常涉及以下几个关键概念: try catch finally throw

  • try 块包含可能会抛出异常的代码。
  • catch 块用于捕获并处理 try 块中抛出的异常。
  • finally 块用于执行清理工作,无论是否发生异常都会执行。
  • throw 用于手动抛出异常。

C#定义了许多内置异常类,它们从基类 System.Exception 派生。例如, System.IndexOutOfRangeException 表示索引不在数组的有效范围内, System.InvalidCastException 表示尝试将对象从一种类型强制转换为不兼容的类型时抛出。

下面是一个简单的异常处理示例:

try
{
    // 尝试执行可能引发异常的代码
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[5]);
}
catch (IndexOutOfRangeException ex)
{
    // 捕获IndexOutOfRangeException异常
    Console.WriteLine("索引超出范围: " + ex.Message);
}
finally
{
    // 最后执行的代码
    Console.WriteLine("执行清理工作");
}

在这个例子中,尝试访问数组 numbers 的第六个元素会抛出一个 IndexOutOfRangeException 异常,因为数组只有三个元素。 catch 块捕获了这个异常,并打印出异常信息。无论是否发生异常, finally 块都会执行。

4.1.2 自定义异常和异常过滤器

C#允许开发者通过创建继承自 System.Exception 的类来创建自定义异常。自定义异常可以提供更具体和有用的错误信息,有助于精确地捕捉和处理错误。

public class MyCustomException : Exception
{
    public MyCustomException(string message) : base(message)
    {
    }
}

异常过滤器(Exception Filters)是C# 6中引入的一个特性,它允许在 catch 块中使用 when 关键字来添加一个条件表达式,只有当表达式为真时, catch 块才会执行。

try
{
    // 可能抛出异常的代码
}
catch (MyCustomException ex) when (ex.Message.Contains("特定错误"))
{
    // 仅当异常消息包含"特定错误"时,才执行此代码块
}

异常过滤器可以提供比异常类型更细粒度的异常处理控制,有助于提高代码的健壮性和错误处理的灵活性。

4.2 委托、事件与Lambda表达式

4.2.1 委托的概念和应用

委托(Delegate)是一种类型,它定义了方法的类型,使得可以将方法作为参数传递给其他方法,或者作为事件的订阅者。

委托可以用于封装方法,以便于可以将方法作为参数进行传递和调用。委托的定义包括返回类型和参数列表,这使得委托实例可以引用任何具有兼容签名的方法。

下面是一个使用委托的简单例子:

// 定义一个委托类型
public delegate int BinaryOp(int x, int y);

// 实现一个具体的方法,符合委托的签名
public int Add(int x, int y) => x + y;

// 实现一个具体的方法,符合委托的签名
public int Subtract(int x, int y) => x - y;

class Program
{
    static void Main()
    {
        // 实例化委托,引用Add方法
        BinaryOp op = new BinaryOp(Add);
        Console.WriteLine(op(5, 3)); // 输出:8

        // 实例化委托,引用Subtract方法
        op = Subtract;
        Console.WriteLine(op(5, 3)); // 输出:2
    }
}

4.2.2 事件驱动编程基础

事件驱动编程是一种编程范式,其中程序的流程由事件(如用户交互)来驱动。在C#中,事件是基于委托的,它们提供了对象通知其他对象发生了某些事情的能力。

事件通常用于实现观察者模式,在这种模式下,一个对象(发布者)触发事件,其他对象(订阅者)响应这些事件。

// 定义事件委托类型
public delegate void EventHandler();

// 定义一个含有事件的类
public class Publisher
{
    // 定义事件
    public event EventHandler RaiseEvent;

    // 方法用于触发事件
    protected virtual void OnRaiseEvent()
    {
        // 空操作,因为可能会被重写
    }

    // 如果RaiseEvent不是空的,使用RaiseEvent()
    public void DoSomething()
    {
        OnRaiseEvent();
    }
}

// 订阅者类
public class Subscriber
{
    private int _count = 0;

    // 订阅方法
    public void Subscribe(Publisher publisher)
    {
        publisher.RaiseEvent += CountUp;
    }

    // 事件处理方法
    private void CountUp()
    {
        _count++;
        Console.WriteLine($"Subscriber 计数: {_count}");
    }
}

class Program
{
    static void Main()
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber();

        // 订阅事件
        subscriber.Subscribe(publisher);

        // 触发事件
        publisher.DoSomething();
        publisher.DoSomething();
    }
}

在这个例子中, Publisher 类有一个事件 RaiseEvent Subscriber 类订阅了这个事件,并定义了一个 CountUp 方法作为事件的处理方法。当 Publisher DoSomething 方法被调用时, RaiseEvent 事件被触发,所有订阅该事件的 Subscriber 实例的 CountUp 方法都会被调用。

4.3 异步编程模型

4.3.1 async和await的使用

随着应用程序变得越来越响应式,异步编程变得越来越重要。C#提供了 async await 关键字,使得异步编程更简洁、更直观。

async 修饰符用于方法、lambda 表达式或匿名方法,表明该方法是异步的。 await 表达式用于等待 async 方法完成。

public async Task<int> GetUserDataAsync()
{
    // 模拟长时间运行的任务
    await Task.Delay(2000);
    return 42;
}

class Program
{
    static async Task Main()
    {
        int result = await GetUserDataAsync();
        Console.WriteLine($"数据是: {result}");
    }
}

在这个例子中, GetUserDataAsync 是一个异步方法,它使用 await 等待一个模拟长时间运行的任务( Task.Delay )。在 Main 方法中,我们同样使用 await 来等待 GetUserDataAsync 方法的完成。这允许主线程继续执行其他任务,而不是被阻塞。

4.3.2 并行编程和任务并行库

在C#中,任务并行库(Task Parallel Library, TPL)提供了一系列工具来帮助开发者利用多核处理器的优势,实现并行和异步编程。

任务是TPL中的核心概念,它代表一个可以在后台执行的单元操作。 Task 类提供了一种表示异步操作的方法,而 Parallel 类提供了一些静态方法来轻松实现并行循环和并行任务的执行。

// 并行循环
Parallel.For(0, 10, i =>
{
    Console.WriteLine($"执行索引为 {i} 的任务");
});

// 并行任务
var task1 = Task.Run(() => { Console.WriteLine("任务 1"); });
var task2 = Task.Run(() => { Console.WriteLine("任务 2"); });

Task.WaitAll(task1, task2);

在这个例子中, Parallel.For 方法用于并行执行一个循环,而 Task.Run 方法用于创建并启动两个并行任务。 Task.WaitAll 方法等待所有任务完成。

C#的异步和并行编程功能提供了一种强大和灵活的方式来构建高性能和响应式应用程序,使开发人员能够更好地利用硬件资源,同时提供流畅的用户体验。

5. C#在Web应用开发中的实践

在当今IT行业中,Web应用开发一直是软件开发领域的一个热点话题,C#凭借其强大和灵活的特点,在Web应用开发领域占有一席之地。在本章中,我们将深入探讨C#在Web应用开发中的应用实践,涵盖MVC架构基础、实现响应式Web应用,以及Web应用的安全与性能优化等关键方面。

5.1 MVC架构基础

5.1.1 MVC设计模式的实现原理

MVC(Model-View-Controller)是一种被广泛使用的软件架构模式,用于将应用程序分为三个主要的组件,以实现关注点分离(Separation of Concerns)。

  • 模型(Model) :代表了应用程序的状态,负责与数据库进行交互,以及实现数据的CRUD(创建、读取、更新、删除)操作。
  • 视图(View) :负责展示数据,即将模型的数据以用户友好的方式显示在界面上。
  • 控制器(Controller) :作为模型和视图的中介,接收用户的输入并调用模型和视图去完成用户的需求。

在C#中,*** MVC框架实现了这一设计模式,并提供了一系列构建Web应用的工具和库。

5.1.2 控制器、模型和视图的角色与交互

在*** MVC中,控制器是处理用户请求的入口。当一个请求到达时,控制器会根据请求参数和业务逻辑选择相应的模型和视图,然后组装响应返回给客户端。

  • 模型 :在MVC中,模型通常是强类型的类,这些类代表了业务数据和数据访问逻辑。
  • 视图 :视图是与用户交互的界面,它通常会与模型结合在一起,从模型中获取数据并展示给用户。
  • 控制器 :控制器处理来自视图的用户输入,并调用模型的业务逻辑,最后选择一个视图来显示输出结果。

下面是一个简单的控制器方法示例,它演示了如何处理一个GET请求,并返回一个视图:

public ActionResult Index()
{
    // 从数据库获取数据
    var products = GetProductsFromDatabase();

    // 将数据传递给视图
    return View(products);
}

5.2 实现响应式Web应用

5.2.1 Web API的应用和RESTful服务

在构建现代Web应用时,Web API已成为一种重要的接口形式。它允许Web应用与其他应用或客户端通过HTTP协议进行通信。*** Web API框架是C#开发人员构建RESTful服务的首选工具。

  • Web API :是一种用于构建可跨平台、跨设备调用的HTTP服务的技术。
  • RESTful服务 :REST(Representational State Transfer)是一种软件架构风格,其中Web API的实现基于REST原则,即使用无状态的HTTP请求来实现数据的操作。

下面是一个创建RESTful服务的简单Web API控制器示例:

public class ProductsController : ApiController
{
    // GET api/products
    public IEnumerable<Product> GetProducts()
    {
        // 这里可以调用业务逻辑来获取产品列表
        return GetProductsFromService();
    }
}

5.2.2 响应式Web设计和Bootstrap框架

随着移动设备的普及,响应式Web设计变得越来越重要。Bootstrap是目前最流行的前端框架之一,它提供了一整套响应式、移动设备优先的工具包。

  • 响应式Web设计 :指的是使用相同代码库开发适应不同屏幕尺寸和设备的Web页面。
  • Bootstrap框架 :允许开发者快速地创建响应式布局,提供了一系列预定义的CSS类和组件。

使用Bootstrap,开发者可以轻松地通过定义不同断点来创建响应式布局。例如:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-6 col-md-4"> <!-- 不同分辨率下不同的列布局 -->
      <!-- 内容 -->
    </div>
  </div>
</div>

5.3 Web应用安全与性能优化

5.3.1 常见的安全威胁和防护措施

安全是Web应用开发中不可忽视的一部分。开发者需要了解并防范各种安全威胁,包括但不限于跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、SQL注入和会话劫持等。

  • 跨站脚本攻击(XSS) :通过注入恶意脚本到用户浏览器进行攻击,可以通过输入验证和输出编码来防御。
  • 跨站请求伪造(CSRF) :利用用户在浏览器中的身份凭证进行操作,通常通过使用CSRF令牌来防护。
  • SQL注入 :通过在数据库查询中注入恶意SQL代码来攻击,可以使用参数化查询来防御。
  • 会话劫持 :攻击者劫持用户的会话来冒充用户身份,可以通过使用安全的会话管理来防范。

5.3.2 性能监控和优化策略

Web应用的性能直接关系到用户体验。因此,性能监控和优化对于保证Web应用的高质量至关重要。性能优化可以从多个方面入手:

  • 代码层面 :优化算法和数据结构,减少不必要的计算和数据库操作。
  • 服务器层面 :使用更强大的服务器或进行负载均衡。
  • 前端优化 :减少HTTP请求数量、使用缓存和压缩等技术来加快页面加载速度。
  • 数据库层面 :优化查询语句,合理使用索引,并进行查询缓存。

具体实践中,开发者可以利用各种性能测试工具来监控应用性能,并依据测试结果进行针对性的优化。

通过这些实践和策略,C#开发者能够构建高效、安全且响应迅速的Web应用,从而在激烈的市场竞争中脱颖而出。

随着我们对C#在Web应用开发中实践的深入理解,我们已经看到了它在创建强大的、可扩展的Web解决方案方面的巨大潜力。无论是对于初学者还是经验丰富的开发人员,本章的内容都提供了宝贵的见解和技巧,帮助他们更好地掌握C#在Web开发中的应用。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:《21天学C#》是一本针对初学者的全面C#编程指南,目的是在三周内帮助读者建立扎实的编程基础,并能够高效开发.NET平台软件。本书介绍了C#的创建背景、基本语法、面向对象特性和.NET框架的架构与组件,还涉及了*** Web应用开发。此外,书中还涵盖了一些高级主题如异常处理、委托、LINQ和异步编程,为读者提供了深入学习C#的机会。本书适合希望提升C#技能的程序员和新手开发者。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值