C# 6插值格式说明符全攻略(资深架构师20年经验总结)

第一章:C# 6插值格式说明符概述

C# 6 引入了字符串插值功能,极大地简化了字符串格式化操作。通过使用 $ 符号前缀,开发者可以在字符串中直接嵌入表达式,并结合大括号 {} 包裹变量或表达式,使代码更清晰易读。

基本语法结构

字符串插值的基本形式为在双引号字符串前添加 $ 符号,随后在花括号内插入变量或表达式:

// 示例:基础插值用法
string name = "Alice";
int age = 30;
string message = $"Hello, my name is {name} and I am {age} years old.";
Console.WriteLine(message);
// 输出:Hello, my name is Alice and I am 30 years old.

支持格式说明符

在插值表达式中,可通过冒号 : 后接标准或自定义格式说明符,对输出值进行格式化。常见格式包括数字、日期和小数位控制。

表达式格式说明符示例输出
{Math.PI:F2}F2(保留两位小数)3.14
{DateTime.Now:yyyy-MM-dd}日期格式化2025-04-05
{12345:N0}N0(千位分隔整数)12,345

复合表达式与条件处理

插值支持在大括号内使用复杂表达式,例如三元运算符或方法调用:

// 示例:使用三元运算符
int score = 85;
string result = $"Your grade is {(score >= 60 ? "Pass" : "Fail")}.";
Console.WriteLine(result); // 输出:Your grade is Pass.
  • 插值字符串在编译时会被转换为 String.Format 调用
  • 支持文化敏感格式化,可通过 IFormatProvider 控制区域设置
  • 可组合使用多个变量与静态方法调用提升灵活性

第二章:基础格式说明符详解与应用

2.1 字符串对齐与填充:理论与实际场景结合

字符串对齐与填充是格式化输出中的基础操作,广泛应用于日志记录、报表生成和数据对齐等场景。通过左对齐、右对齐或居中对齐,可提升信息的可读性。
常见对齐方式及其应用
Python 提供了 `ljust()`、`rjust()` 和 `center()` 方法实现对齐:

text = "User"
print(f"'{text.ljust(10, '-')}'")   # 左对齐,填充 '-'
print(f"'{text.rjust(10)}'")        # 右对齐,默认空格填充
print(f"'{text.center(10, '*')}'")  # 居中,星号填充
上述代码中,`ljust(10, '-')` 将字符串向左对齐,总宽10字符,右侧用 `-` 填充;`rjust` 和 `center` 同理。参数 `width` 指定总长度,`fillchar` 为可选填充字符(默认为空格)。
实际应用场景对比
场景推荐方法说明
日志对齐rjust时间戳右对齐便于扫描
标题展示center视觉居中增强可读性
字段输出ljust保持列左对齐结构清晰

2.2 数字格式化:标准与自定义格式说明符实践

在处理数值输出时,格式化是提升可读性的关键环节。.NET 和 Java 等平台提供了丰富的标准格式说明符,如 "C"(货币)、"N"(数字)、"P"(百分比)等。
常用标准格式示例
  • "C2":显示为带两位小数的货币形式,如 $1,234.00
  • "P1":转换为百分比并保留一位小数,如 75.5%
  • "D6":整数补零至6位,如 000123
自定义格式灵活控制
使用自定义格式字符串可精确控制输出样式。例如:
double value = 1234.56;
string result = value.ToString("##,##0.00"); // 输出:1,234.56
该格式说明符中,# 表示可选位,0 表示强制占位,逗号为千位分隔符,小数点后保留两位。通过组合符号,可实现高度定制化的数字展示逻辑。

2.3 日期时间格式化:精准控制输出样式

在开发中,日期时间的展示需符合用户习惯与区域规范。Go语言通过time包提供灵活的格式化能力。
标准格式化模板
Go使用固定时间Mon Jan 2 15:04:05 MST 2006作为模板,该时间各部分对应特定数值:
  • 2006 表示年份
  • 01 表示月份(两位)
  • 02 表示日期
  • 15 表示24小时制小时
  • 04 表示分钟
  • 05 表示秒
// 示例:自定义输出格式
t := time.Now()
formatted := t.Format("2006-01-02 15:04:05")
// 输出:2025-04-05 14:30:22
上述代码将当前时间格式化为“年-月-日 时:分:秒”形式,便于日志记录或前端展示。
常用预定义常量
常量名输出格式
time.RFC33392006-01-02T15:04:05Z07:00
time.Kitchen3:04PM

2.4 枚举与布尔值的格式化技巧与性能考量

在现代编程中,枚举与布尔值的格式化不仅影响可读性,也对序列化性能产生显著影响。
枚举的字符串化策略
使用常量枚举可避免运行时对象创建开销。例如在Go中:
type Status int
const (
    Pending Status = iota
    Approved
    Rejected
)

func (s Status) String() string {
    return [...]string{"Pending", "Approved", "Rejected"}[s]
}
该实现通过数组索引避免map查找,提升格式化性能。
布尔值的JSON输出优化
默认情况下,布尔字段序列化为true/false。可通过结构体标签控制:
type Config struct {
    Enabled bool `json:"enabled,string"`
}
添加,string可将其编码为"true"/"false"字符串,增强兼容性,但增加解析开销。
  • 优先使用整型表示枚举以减少内存占用
  • 避免频繁的布尔值字符串转换以提升吞吐量

2.5 复合格式化中的嵌套插值处理策略

在复合格式化场景中,嵌套插值常用于动态构建复杂字符串。当外层格式化操作包含内层需先求值的表达式时,解析顺序至关重要。
执行顺序与作用域隔离
为避免冲突,应优先计算内层插值,并确保变量作用域独立。以下示例展示 Python f-string 中的合法嵌套:

name = "Alice"
info = f"User: {f'Profile({name.upper()})'}"
print(info)  # 输出:User: Profile(ALICE)
该代码中,内层 f'Profile({name.upper()})' 先被求值为 Profile(ALICE),再代入外层格式化。嵌套层级不宜过深,建议控制在两层以内以提升可读性。
  • 避免在插值中执行副作用操作
  • 优先使用函数封装复杂逻辑
  • 注意引号匹配与转义规则

第三章:高级格式控制与区域性支持

3.1 使用CultureInfo实现多语言格式适配

在.NET开发中,CultureInfo类是实现全球化应用的核心组件,它允许开发者根据用户的区域设置动态调整日期、数字、货币等格式。
常用区域文化示例
  • zh-CN:中文(简体,中国)
  • en-US:英语(美国)
  • fr-FR:法语(法国)
  • de-DE:德语(德国)
代码示例:格式化日期与数字
using System;
using System.Globalization;

CultureInfo culture = new CultureInfo("fr-FR");
DateTime now = DateTime.Now;
Console.WriteLine(now.ToString("D", culture)); // 输出:jeudi 4 avril 2024
Console.WriteLine(1234567.89.ToString("C", culture)); // 输出:1 234 567,89 €
上述代码通过创建CultureInfo("fr-FR")实例,将日期显示为法语长格式,并以法国本地的千分位和小数点规则格式化货币金额。参数"D"表示长日期模式,"C"表示货币格式,均会根据文化自动适配。

3.2 高精度数值格式化在金融系统中的应用

在金融系统中,金额计算的精度直接影响交易的准确性与合规性。浮点数由于二进制表示的局限,容易引入舍入误差,因此必须采用高精度数值格式化方案。
使用 decimal 包进行精确计算
package main

import (
    "fmt"
    "github.com/shopspring/decimal"
)

func main() {
    amount1 := decimal.NewFromFloat(10.25)
    amount2 := decimal.NewFromFloat(0.1)
    total := amount1.Add(amount2) // 精确结果:10.35
    fmt.Println(total.String())   // 输出: 10.35
}
上述代码使用 Go 的 shopspring/decimal 库,将浮点数转换为十进制高精度类型,避免了 IEEE 754 浮点运算的精度丢失问题。参数 NewFromFloat 将标准 float64 转换为不可变的 decimal 对象,Add 方法执行精确加法。
常见应用场景
  • 跨境支付中的汇率换算
  • 利息与复利的逐笔计算
  • 对账系统中的余额比对

3.3 自定义格式提供器IFormatProvider的扩展实践

在 .NET 中,IFormatProvider 接口为格式化操作提供了一种可扩展机制。通过实现该接口,开发者可以自定义日期、数字或自定义类型的显示格式。
实现自定义格式提供器
public class CurrencyFormatProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        return formatType == typeof(ICustomFormatter) ? this : null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg is decimal value)
            return $"¥{value:F2}";
        return arg?.ToString();
    }
}
上述代码定义了一个货币格式提供器,将 decimal 类型值格式化为以“¥”开头的两位小数字符串。
使用场景示例
  • 多语言环境下的区域性格式适配
  • 企业级报表中统一金额、时间展示规范
  • String.Format 配合实现动态格式渲染

第四章:性能优化与最佳实践

4.1 插值字符串与StringBuilder的性能对比分析

在高频字符串拼接场景中,插值字符串虽语法简洁,但每次调用都会创建新的字符串对象,引发频繁的内存分配与GC压力。相较之下,StringBuilder通过内部缓冲区复用,显著减少对象创建开销。
性能测试代码示例

var sw = Stopwatch.StartNew();
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
    sb.Append($"Item{i}");
var result = sb.ToString();
sw.Stop(); // 记录耗时
上述代码使用 StringBuilder 累加1万次字符串,避免了插值导致的临时对象爆炸。
关键性能指标对比
方式时间消耗内存分配
插值字符串极高
StringBuilder
在大量拼接时,StringBuilder表现出更优的时间与空间复杂度。

4.2 避免常见格式化错误提升代码健壮性

在编写代码时,格式化错误常导致难以察觉的运行时问题。统一代码风格与结构是提升可读性和健壮性的第一步。
使用一致的缩进与括号风格
不一致的缩进易引发逻辑错误,尤其在 Python 等依赖缩进的语言中。推荐使用自动化工具(如 Prettier、gofmt)统一格式。
避免字符串拼接引发的安全隐患

// 错误示例:易受注入攻击
query := "SELECT * FROM users WHERE name = '" + name + "'"

// 正确示例:使用参数化查询
stmt, _ := db.Prepare("SELECT * FROM users WHERE name = ?")
rows, _ := stmt.Query(name)
参数化查询防止 SQL 注入,提升安全性与稳定性。
  • 始终使用语言内置的格式化方法(如 fmt.Sprintf)
  • 避免手动拼接敏感数据
  • 启用静态分析工具检测潜在格式错误

4.3 编译时检查与运行时性能的权衡策略

在现代编程语言设计中,编译时检查与运行时性能之间常存在权衡。强类型系统和静态分析可提前捕获错误,但可能引入泛型擦除或运行时代价。
类型安全与性能折衷
以 Go 泛型为例,编译器在实例化时生成特定代码,提升类型安全:

func Map[T, U any](slice []T, f func(T) U) []U {
    result := make([]U, len(slice))
    for i, v := range slice {
        result[i] = f(v) // 编译期类型验证
    }
    return result
}
该函数在编译时确保类型 T 和 U 的一致性,避免运行时类型断言开销,但会因实例化多个类型组合导致二进制膨胀。
优化策略对比
策略优点缺点
全静态检查高安全性、早报错编译慢、灵活性低
运行时优化执行快、动态适应潜在崩溃风险
合理选择取决于应用场景:系统级程序倾向静态保障,而高性能服务可接受部分动态性以换取吞吐提升。

4.4 在高并发场景下的格式化输出优化方案

在高并发系统中,频繁的字符串拼接与日志格式化会显著增加GC压力。通过对象池技术复用缓冲区可有效降低内存分配开销。
使用 sync.Pool 缓存格式化缓冲区
var bufferPool = sync.Pool{
    New: func() interface{} {
        return new(bytes.Buffer)
    },
}

func FormatLog(message string) []byte {
    buf := bufferPool.Get().(*bytes.Buffer)
    buf.Reset()
    buf.WriteString("[LOG] ")
    buf.WriteString(message)
    data := append([]byte{}, buf.Bytes()...)
    bufferPool.Put(buf)
    return data
}
该方案通过 sync.Pool 复用 bytes.Buffer 实例,避免重复分配内存。每次格式化前调用 Reset() 清空内容,使用后将缓冲区归还池中,显著减少堆内存压力。
性能对比数据
方案吞吐量 (QPS)GC频率
普通字符串拼接12,000高频
sync.Pool优化48,000低频

第五章:未来展望与C#版本演进趋势

随着 .NET 生态的持续演进,C# 语言正朝着更高性能、更强类型安全和更简洁语法的方向发展。未来的 C# 版本将更加注重对现代软件架构的支持,例如云原生应用、微服务以及高性能后端系统。
模式匹配的深度集成
C# 不断扩展其模式匹配能力,从 C# 7 的基础类型匹配到 C# 10 支持递归模式,开发者能以声明式方式处理复杂数据结构。例如:

if (shape is Circle { Radius: >= 10 } c)
{
    Console.WriteLine($"Large circle with radius {c.Radius}");
}
该特性在处理 JSON 解析或领域模型验证时显著提升代码可读性。
源生成器推动编译时优化
源生成器(Source Generators)已成为提升性能的关键工具。通过在编译期生成重复代码,避免运行时反射开销。例如,在序列化场景中,System.Text.Json 已集成源生成器实现零反射序列化:

[GenerateSerializer]
public partial class User
{
    [JsonPropertyName("id")]
    public int Id { get; set; }
}
异步流与取消传播的最佳实践
IAsyncEnumerable<T> 在处理实时数据流(如 IoT 设备上报)中被广泛采用。结合 cancellation token 可实现安全的长周期任务管理:

await foreach (var data in sensorStream.WithCancellation(ct))
{
    await ProcessAsync(data);
}
  • 使用 yield return 实现异步流生成
  • 确保每个异步操作传递 CancellationToken
  • 在 ASP.NET Core 中结合最小 API 构建响应式接口
版本关键特性适用场景
C# 10全局 using、文件级类型定义简化大型项目结构
C# 11原始字符串字面量、required 成员配置对象初始化
C# 12主构造函数、集合表达式DTO 和记录类型简化
下载代码方式:https://pan.quark.cn/s/e2157c05e625 在信息技术领域中,数学问题的复杂求解在很大程度上依赖于数值计算,这在科学计算、工程分析以及数据分析等多个方面尤为重要。线性方程组的求解是数值计算中的一个核心且关键的问题,而雅克比迭代法作为一种有效策略,专门用于处理大规模稀疏线性方程组。这个资源提供了一段采用C++语言编写的雅克比迭代法源代码,配合附带的博客文章,能够帮助使用者深入掌握此方法的基本原理和实际应用。 雅克比迭代法,有时也被称作局部迭代方法,主要用于求解形式为 Ax = b 的线性方程组,其中矩阵A需满足对角占优的条件。对角占优的特性是指矩阵中每个对角线元素的绝对值要大于该行其他元素绝对值之和,这一性质确保了算法的收敛性能。该方法的实施基于矩阵A的雅克比矩阵J,其构成方式为 J = D - L - U,其中D、L和U分别代表矩阵A的对角线部分、下三角部分以及上三角部分。 迭代过程的数学表达式为:x(k+1) = J^-1 * b + (I - J^-1*A) * x(k),在此表达式中,x(k)表示第k次迭代的解向量,x(k+1)则是第k+1次迭代的解向量,I是单位矩阵。每次迭代都利用前一次得到的解来计算下一次的解,迭代会持续进行,直到解的精度达到预设标准或迭代次数达到最大限制。 在使用C++进行编程实现时,主要步骤包括: 1. 初始化阶段:设定初始解向量x(0),并明确迭代过程中的参数,例如最大迭代次数和容许的误差界限。 2. 构建雅克比矩阵:依据矩阵A的非对角元素来形成J矩阵。 3. 迭代计算:依照上述迭代公式计算新的解向量,并验证是否满足终止条件(即当前解与前一次解的差值小于设定的误差界限)。 4. 结果输出...
源码下载地址: https://pan.quark.cn/s/24e22475d2c3 采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。采用SSM框架构建的果蔬生鲜超市平台,亦称为果蔬在线交易系统。其用户界面部分涵盖了:账号登录流程、新用户注册功能、购物车内容维护、订单状态监控、收货地点设置、商品检索服务、商品购买操作等。系统后台则由以下核心单元构成:用户账户维护、收货地址簿维护、商品分类维护、商品信息维护、货品出库单维护、订单状态跟踪、销售业绩统计、系统整体配置等。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在当前文档中,我们将详细研究如何运用Eclipse集成开发环境(IDE)的自定义CSS选项来调整其所有视窗的背景色调以及其他常用视窗的色调。Eclipse作为一个功能强大的开源开发平台,能够支持多种编程语言,包括Java、C++以及Python等。对于那些长时间运用Eclipse的开发专业人士而言,个性化界面色调能够显著提升工作舒适感和效率。让我们深入理解Eclipse的色彩配置机制。Eclipse依托于SWT(Standard Widget Toolkit)框架,允许用户通过调整主题和CSS样式来改变其视觉呈现。在默认设置下,Eclipse会采用系统级别的视窗色调,但用户可以通过覆盖特定的CSS文件来实现个性化定制,而无需触及操作系统本身的设置。 实施步骤1:定位Eclipse的CSS文件 Eclipse的CSS文件通常存储在以下路径位置: ``` <eclipse安装目录>\plugins\org.eclipse.platform_<version>\css ``` 此处,`<eclipse安装目录>`代表用户安装Eclipse的文件夹位置,`<version>`指代Eclipse的版本标识。 实施步骤2:对原始CSS文件进行备份 在进行任何修改之前,务必对原CSS文件进行备份操作,以便在出现问题时能够迅速恢复到原始状态。备份文件通常命名为`e4.css`和`e4_basestyle.css`。 实施步骤3:建立或编辑CSS文件 创建一个新的CSS文件(例如`custom_theme.css`),并插入以下内容以设定窗口背景色: ```css .e4-applicatio...
代码下载地址: https://pan.quark.cn/s/a4b39357ea24 根据所提供的文件资料可以判断,这是一份关于RS232转422/485转换器电路原理图的详尽设计文档。该文档全面地列出了电路中各个组件及其连接方法,对于掌握RS232与422/485之间的信号转换原理具有非常重要的参考意义。 ### RS232、RS422与RS485概述 在开始深入剖析电路原理图之前,有必要先对RS232、RS422与RS485这三种通信协议的基本概念进行简要介绍。 #### RS232 RS232是一种应用于串行数据通信的接口规范,主要适用于计算机与调制解调器或其他外部设备之间的数据交互。该接口标准支持点对点的通信模式,通信距离通常不超过15米,并且较为容易受到外界干扰的影响。 #### RS422 RS422是一种经过改进的串行通信标准,其核心特点在于采用差分信号进行传输,支持多点的通信模式,即一个发送端能够同时向多个接收端传输数据,通信距离最远可达1200米,并且具有较强的抗干扰性能。 #### RS485 RS485是建立在RS422基础之上的进一步发展,同样运用差分信号进行传输,其最突出的特点在于支持半双工通信模式,即在同一时刻只能进行发送或接收操作,但发送端和接收端的位置可以互换,非常适合于长距离、多设备之间的数据传输,通信距离同样可以达到1200米,并且能够支持多达32个设备接入。 ### RS232转422/485转换器电路解析 在电路原理图中,可以观察到采用了MAX490CPA和MAX485CPA芯片作为RS232与RS422/485之间的信号转换装置,同时使用了MAX233ACPP芯片作为RS232电平转换装置。 #### MAX490CP...
内容概要:本文档系统汇集了“计及电动汽车充电站接入的配电网承载能力评估与优化”的Matlab代码实现资源,覆盖无功优化、多时间尺度调度、N-1/N-k故障分析、电动汽车V2G技术、微电网协调调度、电氢耦合系统、风光储联合系统等多个电力系统前沿研究方向。资源以Matlab/Simulink为核心工具,辅以Python,提供大量可复现的科研代码实例,涵盖从建模、优化算法(如NSGA-II、DDPG、MPC、PSO等)到仿真验证的全流程。同时拓展至机器学习、深度学习、路径规划、信号处理、无人机控制、综合能源系统优化等多个交叉领域,配套网盘资料与公众号支持,助力科研人员高效开展创新研究与高水平论文复现。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电气工程、能源互联网、智能电网、综合能源系统等方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究电动汽车大规模接入对配电网安全性、稳定性及承载力的影响;②构建含V2G的无功优化与电压协同控制模型;③实现多时间尺度下微电网与配电网的协调调度;④复现N-1/N-k故障下的安全约束调度、鲁棒恢复等复杂优化模型;⑤开展综合能源系统、电氢氨耦合系统等新兴领域的仿真与优化研究; 阅读建议:建议结合提供的网盘资源与公众号内容体系化学习,优先掌握核心案例的算法架构与建模逻辑,按研究主题分类深入,并注重将理论方法与代码实践紧密结合,提升科研效率与创新能力。
已经博主授权,源码转载自 https://pan.quark.cn/s/baa6fed0ef20 **SHT20温湿度传感器简介** SHT20是由瑞士Sensirion公司制造的精密数字型温湿度检测设备,在环境检测、智能家居、农业、医疗装置及工业自动化等多个领域得到普遍运用。该传感器凭借其高精确度、低能耗以及稳定的运作表现,赢得了业界的广泛认可。 **传感器工作机制** SHT20的核心技术在于电容式湿度检测与NTC热敏电阻的温度测量。湿度检测部分通过感知水分子对传感器表面硅聚合物膜层的作用来判定相对湿度(RH),而温度检测部分则借助热敏电阻的电阻值随温度变化的特性来计量环境温度。 **核心优势** 1. **高精确度**:SHT20能够提供±2%RH的湿度检测准确度和±0.3°C的温度检测准确度,在同类型产品中表现卓越。 2. **低能耗**:在设计中注重节能,适合用于电池供电或能量收集系统,工作电流可小至1.1μA。 3. **迅速响应**:响应速度快,能迅速适应环境变化,对于实时监测具有关键意义。 4. **I²C接口**:采用标准的I²C数字接口,便于融入各种微控制器系统中。 5. **全范围测量**:支持0% to 100%RH的湿度和-40°C to +125°C的温度测量范围。 6. **紧凑封装**:小型化封装设计,节省空间,方便安装在有限空间内。 **使用场景** 1. **智能家居**:用于智能空调、加湿器和除湿机,实现室内环境自动调节以提升舒适度。 2. **农业管理**:温室环境监控,协助控制作物生长的最佳条件。 3. **医疗装置**:呼吸机、冷藏设备等,保障药品和样本的储存条件。 4. **环境监测**:空气质量监测站,气象站,提供精确的气象...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值