深入.NET平台和C#编程

深入.NET平台和C#编程 知识点整理

北大青鸟

 

目录

第一章 深入.NET框架

一、.NET结构

二、CLR的两个组成部分

CTS

CLS

三、核心类库及命名空间

四、封装

  是面向对象的三大特征之一 

    封装·类

五、类的属性

六、总结

 

第二章 深入 C# 数据类型

一、常用数据类型

二、结构

三、数据类型

四、引用类型和值类型

五、封装的特点:

六、总结

第三章 使用集合组织相关数据

一、 ArrayList是一个可动态维护长度的集合

(1)如何实现:

(2)添加元素:

(3)访问ArrayList中的单个元素

(4)ArrayList的遍历

(5)删除ArrayList的元素

(6)常见错误:

2、通过Hashtable获取对象

(1)定义 特点

(2)给Hashtable添加元素

(3)获取Hashtable的元素

(4)删除Hashtable的元素

(5)如何遍历Hashtable

(6)使用集合存储时容易出现的问题

三、List(泛型集合)

(1)什么是泛型集合

(2)使用步骤

(3)List 与 ArrayList 对比

四、Dictionary,v>

(1)定义

(2)如何new

(3)添加

(4)通过key获取元素

(5)通过Key删除元素

(6)遍历

(7)Dictionary与Hashtable,v>

五、泛型的重要性

六、总结​

第四章 深入类的方法

一、构造函数

(1)作用 初始化变量

(2)特点(老郑)

(3)参数

(4)注意

二、方法重载

(1)什么是方法重载

(2)最经典的举例

第五章 体检套餐管理系统

(1)关键代码

第六章 初识继承和多态

一、继承

(1)概述

(2)如何实现继承

(3)base调用父类成员

2、访问修饰符

(5) is a的应用

三、方法重写

(1)在父类里的方法

(2)在子类的方法(重写父类方法)

(3)注意

四、多态

(1)什么是多态

第七章 深入理解多态

一、里氏替换原则(LSP)

二、操作符:is 与 as操作符

(1)is:

(2)as:

三、抽象方法与抽象类

(1)什么是抽象方法

(2)如何实现

(3)对比虚方法

四、面向对象的三大特性

    封装

    继承

    多态

第八章 可扩展标记语言XML

一、XML可扩展标记语言

(1)解析XML文件

(2)TreeView的使用

1.TreeView空间重要属性和事件

2.节点对象的属性

3.为TreeView空间添加根节点

为某个选择子节点添加子节点

 4.TreeView删除节点

  5.清空节点

第九章 文件操作

一、文件读写

(1)步骤

(2)创建文件流

(3)创建写入器和读取器

(4)将数据写入文本文件

(5)读取文本文件

(6)文件操作

(7)File类与Directory类

(8)静态成员

1.使用staic修饰符

2. 静态成员的使用

3.  静态成员与实例成员

FrileInfo类

DirectoryInfo类

第十一章  影院售票系统


第一章 深入.NET框架

一、.NET结构

.net框架
    类库(FCL)
    公共语言运行时(CLR)
        CLS
        CTS
 
.NET结构
.NET结构

二、CLR的两个组成部分

CTS

        称为为通用类型系统

        定义了在IL中的数据类型

CLS

        称为公共语言规范

        包括集中面向对象的编程语言的通用功能

三、核心类库及命名空间

      核心类库说明

            命名空间

使用泛型

System.Collections.Generic

对文件的基本操作

System.IO

对网络协议进行编程

System.net

对数据库的访问

System.Data

开发Windows应用程序

System.Windows.Forms

对GDI+基本图形的操作

System.Drawing

四、封装

  是面向对象的三大特征之一 

        一个不可分割的独立实体

        隐藏内部的细节

        保留对外接口

    通过访问修饰符授权

    封装·类

        保证数据的安全性

        提供清晰的对外接口

        类的内部实现可以任意修改 ,不影响其他类

五、类的属性

可读性、只读、只写
    示例
private string _name;  //姓名public string Name
{
        get { return _name; }
        set { _name = value; }
}

可简化为:

public string Name { get; set; }

 

    快捷键: prop + tab + tab
    适用场合:不对字段进行逻辑验证的操作

六、总结

 


第二章 深入 C# 数据类型

一、常用数据类型

 数据类型按存储方式可分为两类:值类型和引用类型 

常用数据类型

Java

C#

举例

整型

int

int

年龄

浮点型

float

float

成绩

双精度型

double

double

圆周率

布尔型

boolean

bool

是否少数民族

枚举类型

enum

enum

颜色

字符串

String

string

家庭住址

二、结构

访问修饰符 struct 结构名
{
       定义结构成员
}

 当对象需要用较少的字段来表示时,可以选用结构

    结构是值类型,数据提取速度快

    但是频繁的赋值操作会占用较大空间, 在开发中多数情况下都定义为类!!!

三、数据类型

 

值类型

引用类型

源自

System.ValueType

System.Object

存储方式

存储值

存储对象引用

常用类型

基本数据类型

整型:int

基类:System.Object

长整型:long

浮点型:float、double

 

字符型:char

自定义类:class

布尔型:bool

枚举类型(enum)

接口

结构类型(struct)

数组

四、引用类型和值类型

    引用类型的赋值不是内容复制,是把地址复制

    值方式传递引用类型参数

        参数在方法中被修改

    值方式传递值类型参数

        不会被修改

值传递+值类型                不变

值传递+引用类型            变

引用传递ref+值类型            变

引用传递ref+引用类型            变

不同类型参数传递

参数变化是否保留

值方式传递值类型

值方式传递引用类型

引用方式(ref)传递值类型

引用方式(ref)传递引用类型

五、封装的特点:

1.结构可带有方法、字段、索引、属性、运算符方法和事件。

2.结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。

3.与类不同,结构不能继承其他的结构或类。

4.结构不能作为其他结构或类的基础结构。

5.结构可实现一个或多个接口。

6.结构成员不能指定为 abstract、virtual 或 protected。

7.当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。

8.如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。

六、总结


第三章 使用集合组织相关数据

一、 ArrayList是一个可动态维护长度的集合

(1)如何实现:

        1、引入System.Collections命名空间

          2.实例化ArrayList对象

(2)添加元素:

        用Add添加 添加一个对象到集合的末尾    返回索引

        向ArrayList中添加值类型的元素时会执行装箱处理

(3)访问ArrayList中的单个元素

(类型) ArrayList [index]  //按指定索引(下标)取得对象

需要类型转换

(4)ArrayList的遍历

1.使用和数组类型的方式(通过索引

for (int i = 0; i < engineers.Count; i++)
{
        SE seFor = (SE)engineers[i];
        Console.WriteLine(seFor.Name);
}

  2.使用foreach方式 (通过对象)

foreach (Object obj in engineers)
{
         SE seForeach = (SE)obj;
         Console.WriteLine(seForeach.Name);
}

(5)删除ArrayList的元素

        删除一个元素 剩余的元素会自动调整索引

(6)常见错误:

        未引入命名空间

        定义是未实例化

2、通过Hashtable获取对象

(1)定义 特点

        动态可维护长度
        可通过关键词检索
        根据键(Key)可以查找的对应的值(Value)
            键和值一一对应(键不可用重复、值可以重复)

(2)给Hashtable添加元素

     .Add(Key,Value);

(3)获取Hashtable的元素

类型 名=(类型)Hashtable[“key”];  //通过key获取元素

(4)删除Hashtable的元素

Hashtable.Remove(“key”);          //通过Key删除元素

(5)如何遍历Hashtable

不能遍历整个对象,而是遍历Values

foreach(Object obj in engineers.Values)
{
    SE se = (SE)obj;
    Console.WriteLine(se.Name);
}

  可以遍历Keys

foreach (Object obj in engineers.Keys)
{
    Console.WriteLine((string)obj);
}

  可以遍历键值对

foreach (DictionaryEntry en in engineers)
{
    Console.WriteLine((string)obj);
    Console.WriteLine(((SE)en.value).Name);
}

(6)使用集合存储时容易出现的问题

        1.对象存储不易控制
        2.类型转换容易出错

三、List<T>(泛型集合)

(1)什么是泛型集合

            泛型<T>是最常见的用途是创建集合类

            泛型集合可以约束集合内的元素类型

            典型泛型集合List<T>、DIctionary<K,V>

(2)使用步骤

              1.命名空间:System.Collections.Generic

            2.创建List<T>泛型集合

            3.遍历无序类转换

foreach (SE se in engineers)
{
       MessageBox.Show(se.SayHi());
}

(3)List<T> 与 ArrayList 对比

异同点

      List<T>

           ArrayList

不同点

增加元素时类型严格检查

可以增加任何类型

添加和读取值类型元素时,无需装箱拆箱

添加和读取值类型元素时,需要装箱拆箱

相同点

通过索引访问集合的元素

添加对象方法相同

通过索引删除元素

四、Dictionary<K,V>

(1)定义

           Dictionary<K,V>通常称为字典

            <K,V>约束集合中元素类型

            编译时检查类型约束

            无需装箱拆箱操作

(2)如何new

Dictionary<Key,Value> dic = new Dictionary<Key,Valu>();

(3)添加

dic.Add(Key,Value);

(4)通过key获取元素

value ee=div[key];

(5)通过Key删除元素

dic.Remove(Key);

(6)遍历

//Dictionary<string, SE> 方式
foreach (SE se in engineers.Values)
{
         MessageBox.Show(se.SayHi());
}

(7)Dictionary<K,V>与Hashtable

异同点

      Dictionary<K,V>

Hashtable

不同点

增加元素时类型严格检查

可以增加任何类型

无需装箱拆箱

需要装箱拆箱

相同点

通过Key获取Value

添加对象方法相同

遍历方法相同

五、泛型的重要性

1.代码重用,未来的主流技术

2.性能高,避免繁琐的装箱拆箱

3.提供了更好的类型安全性

4.CLR支持泛型

六、总结


第四章 深入类的方法

一、构造函数

(1)作用 初始化变量

(2)特点(老郑)

         特殊的方法
        函数名必须和类名相同
        没有返回值
        作用是完成对象的初始化工作(new的时候会被调用)
        如果自己不写,系统提供一个无参构造函数
            一旦自己写了一个(无参或有参),系统就不再提供无参构造函数

(3)参数

            带参可以在new 的时候在后面的()给值  (作用)简化对象属性的初始化
                注意:调用带参构造函数一定要使  传入的参数和参数列表对应

(4)注意

        每个类都默认有一个无参数的构造函数,一旦手动添加了构造函数,系统就不会再给类添加无参构造函数
        所以只要写 就写2个

二、方法重载

(1)什么是方法重载

            提供多种实例化对象的方式  也包括构造函数
            方法重载:同一个类中,方法名相同,参数列表不同(参数类型不同、参数个数不同)
                简称 同类  同名    不同参

(2)最经典的举例

            Console类提供多个重载的WriteLine()  接收不同类型的数据做为参数  方便记忆,调用

第五章 体检套餐管理系统

(1)关键代码


第六章 初识继承和多态

一、继承

(1)概述

        在C#中,类可以继承自另一个类

        衍生的类(子类)继承父类的方法和数据成员

        子类继承父类,父类派生子类

            父类又叫基类

            子类又叫派生类

class 子类:父类
{......  }
  继承是面向对象的一个重要特性
        父类-子类
        基类-衍生类(C# base)
        超类-派生类(java super)
        C#中子类不能继承多个父类

(2)如何实现继承

        子类:父类
            子类继承父类的公共属性
            子类拥有自己独有的属性

(3)base调用父类成员

        子类用base.  父类的属性
        子类构造函数会隐式调用父类无参构造函数
        用base()调用父类的构造函数
public SE(string id,string name,int age, Gender gender, int popularity)//线束调用父类的构造函数  
         : base(id, age, name, gender)
{
    this.Popularity = popularity;//公共属性在父类构造函数中初始化,代码简洁、冗余少
}

2、访问修饰符

 public        公共的,谁都可以

private        私有的,只有自己可以

protected    受保护的,自己和子类可以

internal        只有在同一个程序集的文件中,内部类型或者是成员才可以访问

 

类内部

子类

其他类

public

可以

可以

可以

private

可以

不可以

不可以

protected

可以

可以

不可以

(5) is a的应用

        子类 is a 父类,子类可以加入父类类型的泛型集合List<Employee>。即SE或PM对象都可以加入集合empls中
        is进行类型检查 判断类型

三、方法重写

(1)在父类里的方法

public virtual string SayHi()//用virtual关键词修饰
{
        string message = string.Format("大家好!");
        return message;
}

虚方法

访问修饰符  virtual  返回值类型  方法名()
{
    //方法体
}

(2)在子类的方法(重写父类方法)

public override string SayHi() {……}  //用override关键字修饰

方法重写

访问修饰符  override  返回值类型  方法名()
{
    //方法体
}

(3)注意

父类中定义的虚方法并非必须被子类重写。在父类中可给出虚方法的默认实现。如果子类不重写父类的虚方法,依然执行父类的默认实现;反之,则执行子类重写后的方法

四、多态

  方法重载也是实现多态性的一种方式。只不过重载的方法都在同一个类中,而用虚方法实现多态的方法分散在有继承关系的多个类中

(1)什么是多态

    指同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
    方法名、参数列表、返回值一样,提供不同的实现
    定义父类变量,创建子类对象。根据实际创建的对象类型,决定执行哪个方法。呈现多态性!
重载
    同类,同名,不同参
重写
    父子类,同壳,不同芯
 
虚方法
    virtual
    基本和普通方法一样
    出现在父类
    子类可以重写父类的虚方法
    如果子类重写,调用子类重写后的方法,否则就调用父类的虚方法

第七章 深入理解多态

一、里氏替换原则(LSP)

     在一个软件系统中,子类对象可以替换所有使用的父类对象,且程序行为没有变化
    子类可以替换父类    new一个父类的集合 可以放入子类

二、操作符:is 与 as操作符

(1)is:

if (empls[i] is SE) {}  //判断empls集合的元素是否是SE对象

(2)as:

for (int i = 0; i < empls.Count;i++ )
{
    if (empls[i] is SE)
    {
        SE se = empls[i] as SE;   //一种类型转换方式,讲empls集合的元素转化成SE对象 转换失败返回null;
        Console.WriteLine(se.SayHi());
    }
}
  用as操作符进行类型转换不会产生异常,但着并不代表不需要异常处理
 
 
is
    类型判断,返回true/false
as
    做类型转换
    如果转换失败,不会报错,返回null

三、抽象方法与抽象类

(1)什么是抽象方法

    一个没有实现的方法(没有方法体)
    只存在于抽象类里
        有抽象方法的类必然是抽象类
        但是,抽象类中的方法并不一定都是抽象方法
[访问修饰符]  abstract  class 类名{    [访问修饰符]  abstract  返回类型 方法名();}
 抽象类用来列举一个类所需要的行为
    抽象类不明确提供具体实现方法
    抽象类必须由其子类实现它的抽象方法(除非子类也具有抽象性)
 
    抽象类不能被实例化

(2)如何实现

    1.使用override实现抽象方法的重写
 

(3)对比虚方法

    抽象类和抽象方法
        抽象类通常代表一个抽象的概念
        抽象方法约束对象的行为
    虚方法
    具体类的默认实现,提供子类的扩展属性方法

抽象方法

虚方法

用 abstract 修饰

用 virtual 修饰

不允许有方法体

要有方法体,哪怕是一个分号

必须被子类 override

可以被子类 override

只能在抽象类中

除了密封类都可以写

抽象类中可以包括抽象方法和非抽象方法
抽象类:
    abstract
    表明这个类不是一个具体的类,是抽象的,是概念的
    不能new
    可以有抽象方法,也可以有普通方法
    可以有构造函数
    不能是密封的(sealed),也不能是静态的(static)
 
 
抽象方法:
    abstract
    表明这个方法仅仅是个理论上的功能,不具备实际功能
    没有方法体
    只能存在与抽象类中
    子类必须重写抽象方法,除非子类也是抽象类

四、面向对象的三大特性

    封装

隐藏内部实现,稳定外部接口

    继承

子类继承父类成员,实现代码复用

    多态

不同于子类对同一个消息做出的不同的反应


第八章 可扩展标记语言XML

一、XML可扩展标记语言

(1)解析XML文件

XmlDocument myXml = new XmlDocument();                     //用于解析XML文件的类
myXml.Load("Engineer.xml");                                //加载制定的XML数据
XmlNode engineer = myXml.DocumentElement;                  //获取根节点
foreach (XmlNode node in engineer.ChildNodes )             //获取当前节点的所有子节点
{
        switch (node.Name)                                 //当前节点名字
        {
                    case "Name":
                        Console.WriteLine("姓名:{0}",node.InnerText);//当前节点的值
                        break;
                    //…
        }
}

XmlDocument对象表示XML整个文档

XmlNode对象表示XML文件的单个节点

对象

属性和方法

说明

XmlDocument

DocumentElement 属性

获取文档的根

ChildNodes 属性

获取节点的所有子节点

void Load()方法

加载整个XML的结构

XmlNode

InnerText 属性

当前节点的值

Name属性

当前节点的名字

ChildNodes 属性

当前节点的所有子节点

(2)TreeView的使用

1.TreeView空间重要属性和事件

    Nodes属性:TreeView控件中的所有树节点
    SelectedNode属性:当前TreeView控件中选定的树节点,如果当前没有选定树节点,返回值为null
    AfterSelect事件:选定树节点之后发生

2.节点对象的属性

属性

说明

Text

节点显示的文本 

Index

节点在所在集合中的索引 

Parent

节点的父节点(TreeNode) 

Level

节点在树形菜单中的层级0、1…..

Tag

节点值

Nodes

节点的所有下一级子节点 

3.为TreeView空间添加根节点

TreeNode rootNode = new TreeNode("音乐频道");
this.tvMenu.Nodes.Add(rootNode);

为某个选择子节点添加子节点

this.tvMenu.SelectedNode.Nodes.Add(node);

 4.TreeView删除节点

this.tvMenu.SelectedNode.Remove();

  5.清空节点

this.tvMenu.SelectedNode.Nodes.Clear();//经常用在刷新TreeView显示前

this.tvMenu.Nodes.Clear();  //清空TreeView控件中所有节点

//    树状菜单的清空方法常用在更新树状菜单方法的最前面,这样可以保证节点不被重复加载


第九章 文件操作

一、文件读写

(1)步骤

        创建一个文件流 → 创建相应的读写器(reader and writer)→ 执行读写操作 → 关闭读写器(reader and writer)→ 关闭文件流

(2)创建文件流

    1.引入System.IO命名空间——通过文件操作的类
    2.文件流(FileSream类)用于读写文件
FileStream myfs = new FileStream( string path,  FileMode mode  );
//path制定文件路径
//mode如何打开文件

FileMode枚举

        Create:创建一个新文件。如果文件存在,则改写旧文件

        Open:指定打开现有文件。指定的文件必须存在,否则会发生异常

        CreateNew:新建一个文件。如果文件存在会发生异常,提示文件已经存在

        Append:打开现有文件追加

    转义符:

string path ="D:\\Text.txt";
string path =@"D:\Text.txt";

(3)创建写入器和读取器

    文本文件写入器:SteamWriter

StreamWriter mySw = new StreamWriter(myfs);//传入文件流
mySw.Write(content);//写入方法
mySw.WriteLine(content);//写入一行数据的方法

文件文本读取器

StreamReader mySr = new StreamReader(myfs);//传入文件流
content = mySr.ReadToEnd();//读取到文件末尾
content = mySr.ReadLine();//读取一行

(4)将数据写入文本文件

FileStream myfs = new FileStream(path, FileMode.Create);//创建一个文件流
StreamWriter mySw = new StreamWriter(myfs);//创建写入器
mySw.Write(content);//写入操作
mySw.Close();//关流
myfs.Close();//关器

如果一个程序用了多个流、读写器,它们的关闭顺序一般要和自身在程序中被创建的顺序相反

(5)读取文本文件

     使用OpenFileDialog控件显示打开文件的窗口

this.ofdMain.ShowDialog();  
string path = ofdMain.FileName;  //选择文件
string content;
//……
FileStream myfs = new  FileStream(path, FileMode.Open);//创建一个文件流
StreamReader mySr = new StreamReader(myfs);//创建读取器
content = mySr.ReadToEnd();//讲流从当前的位置堵到末尾
txtContent.Text = content;
mySr.Close();//关闭
myfs.Close();

  解决读取时的中文乱码

FileStream myfs = new FileStream(path, FileMode.Open);
//读取器
StreamReader mySr = new StreamReader(myfs, Encoding.Default);//默认使用Unicode字符,  设置Encoding改变默认设置
content = mySr.ReadToEnd();                                //Encoding.UTF8或Encoding.Default或Encoding.GetEncoding("XXX")
txtContent.Text = content;
//……

     Encoding.UTF8或

        Encoding.Default或

        Encoding.GetEncoding("XXX")

(6)文件操作

        File类:提供操作文件的各种方法

方法

说明

bool  Exists(string path)

用于检查指定文件是否存在,该方法返回一个布尔值

void  Copy(string  

    sourceFileName,

    string destFileName)

将指定路径的源文件中的内容复制到目标文件中,如果目标文件不存在,则在指定路径中新建一个文件

void  Move (string 

    sourceFileName,

    string destFileName)

将指定文件移动到一个新的路径

void  Delete(string path)

删除指定的文件,如果指定的文件不存在,则不引发异常

   操作实例

//检查一个文件是否存在
if (!File.Exists(this.txtFileName.Text))
{
    MessageBox.Show("文件不存在");
}
else
{
    //将源文件复制到一个新文件
    File.Copy(this.txtFileName.Text, this.txtCopyName.Text);
    MessageBox.Show("复制成功!");
}

 Directory 类提供对文件夹的移动、删除等操作

方法

说明

bool  Exists(string path)

用于检查指定文件夹在磁盘上是否存在

void  Move(string 

用于将文件或目录及其内容移到新位置

    sourceDirName,

    string destDirName)

void  Delete(string path,

删除指定目录,如果bool指定true,则删除子目录中的所有目录内容

    bool recursive)

void  Delete(string path)

从指定路径删除空目录

(7)File类与Directory类

//静态

public static class File
public static class Directory

静态类

非静态类

用static修饰

不用static修饰

只包含静态成员

可以包含静态成员

不可以包含实例成员

可以包含实例成员

使用类名调用静态成员

使用实例对象调用非静态成员

不能被实例化

可以被实例化

不能包含实例构造函数

包含实例构造函数

(8)静态成员

1.使用staic修饰符

        静态成员为一个类的所有实体所共享,它属于类,而不属于类的某个对象!例如:太阳

            静态成员方法,提供独立于 特定对象之外的普遍功能

class 类名
{
         public static 数据类型  变量名;   
         public static 返回值类型  方法名(参数列表)
         {
               //方法体;
         }
}

2. 静态成员的使用

    调用静态成员
类名.变量名 = XX;    //给变量赋值
类名.方法名();          //调用静态方法
当类不会有多个对象而更像是一个公用类的时候,
或当方法或属性是“公用”信息的时候声明为静态的比较好!
静态方法只能调用静态方法
静态成员只能由类名调用

3.  静态成员与实例成员

    使用static修饰的成员成为静态成员
    使用实例对象调用的成员成为实例方法

静态方法

实例方法

static关键字

不需要static关键字

使用类名调用

使用实例对象调用

可以访问静态成员

可以访问静态成员

不可以直接访问实例成员

可以直接访问实例成员

调用前初始化

实例化对象时初始化

提供实例方法的文件类

FrileInfo类

属性/方法

说明

Exists

用于检查指定文件是否存在,返回一个布尔值

Extension

获取表示文件扩展名部分的字符串

Name

获取文件名

FullName

获取目录或文件的完整目录

FileInfo  CopyTo(string)

将现有文件复制到新文件,不允许覆盖现有文件

void  Delete()

永久删除文件

void  MoveTo(string)

将指定文件移到新位置

由于File类的静态方法在使用时都会进行安全检查,所以如果想要多次使用某个文件对象,可以考虑使用FileInfo类相应的实例方法,因为并不总是需要安全检查

DirectoryInfo类

方法

说明

DirectoryInfo[ ]  GetDirectories()

返回当前目录的子目录对象数组

FileInfo[ ]  GetFiles()

返回当前目录下文件列表(FileInfo对象数组)

如果打算多次重用某个目录对象,可以考虑使用DirectoryInfo类的实例方法

 


第十一章  影院售票系统

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾拾柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值