【C#基础】C#理论基础

来源:互联网 发布:call死你软件 编辑:程序博客网 时间:2024/06/04 18:18

Day 2
1、注释符
1)、注销
2)、解释

2、c#的3种注释符
1)、单行注释 //
2)、多行注释 /要注释的内容/
3)、文档注释 /// 多用来解释类或者方法

3、变量
用来在计算机当中存储数据。

孙全 开房
火车 26小时 去旅馆睡觉
孙全 一个人 单人房 308
孙全 and girl 双人间 一张床 521
孙全 and boy 双人间 两张床 520

存储整数100
数据类型:整数
在内存中开辟的空间应该是整数类型 int

存储变量的语法:
变量类型 变量名;
变量名=值;

“=”号:在这并不表示等于的意思,而是赋值的意思,表示把等号右边的值赋值给等号左边的变量。

声明并且给变量赋值的简写形式:
变量类型 变量名=值;

4、数据类型
1)、整数类型:int 只能存储整数,不能存储小数。
2)、小数类型:double 既能存储整数,也能存储小数,小数点后面的位数 15~16位。
3)、金钱类型:decimal:用来村粗金钱,值后面需要加上一个m.
4)、字符串类型:string,用来存储多个文本,也可以存储空,字符串类型的值需要被 双引号引来,
这个双引号必须是英文半角状态下的双引号
5)、字符类型:char,用来存储单个字符,最多、最少只能有一个字符,不能存储空。
字符类型的值需要用 单引号因起来。英文半角状态下的单引号。

5、波浪线
1)、如果你的代码中出现了红色的波浪线,意味着你的代码中出现了
语法错误。
2)、如果你的代码中出现了绿色的波浪线,说明你的代码语法并没有错误,
只不过提示你有可能会出现错误,但是不一定会出现错误。警告线

6、变量的使用规则
如果你要是用变量的话,应该要先声明再赋值再使用。

7、命名规则:
**首先要保证的就是这个变量的名字要有意义。
1 现阶段给变量起名字的时候都以字母开头
2 后面可以跟任意“字母”、数字、下划线.
注意:
1)你起的变量名不要与c#系统中的关键字重复.
2)在c#中,大小写是敏感的. HTML
3)同一个变量名不允许重复定义(先这么认为,不严谨)

给变量起名字的时候要满足两个命名规范:
1、Camel 骆驼命名规范。要求变量名首单词的首字母要小写,其余每个单词的首字母要大写。
多用于给变量命名。
2、Pascal 命名规范:要求每个单词的首字母都要大写,其余字母小写。多用于给类或者方法命名。
HighSchoolStudent

highSchoolStudent

8、赋值运算符
=:表示赋值的意思,表示把等号右边的值,赋值给等号左边的变量。
由等号连接的表达式称之为赋值表达式。
注意:每个表达式我们都可以求解除一个定值,对于赋值表达式而言,等号左边的变量的值,
就是整个赋值表达式的值。
int number=10;

9、+号的作用
1)、连接:当+号两边有一边是字符串的时候,+号就起到连接的作用。
2)、相加:两边是数字的时候

10、占位符
使用方法:先挖个坑,再填个坑。
使用占位符需要注意的地方:
1、你挖了几个坑,就应该填几个坑,如果你多填了,没效果。
如果你少填了,抛异常。
2、输出顺序:按照挖坑的顺序输出。

11、异常
异常是指:语法上并没有任何错误,只不过在程序运行的期间,由于某些原因出现了问题,
使程序不能再正常的运行。

12、转义符
转义符指的就是一个’\’+一个特殊的字符,组成了一个具有特殊意义的字符。
\n:表示换行
\”:表示一个英文半角的双引号
\t:表示一个tab键的空格
\b:表示一个退格键,放到字符串的两边没有效果。
\r\n:windows操作系统不认识\n,只认识\r\n
\:表示一个\

@符号
1、取消\在字符串中的转义作用,使其单纯的表示为一个’\’
2、将字符串按照编辑的原格式输出

13、算数运算符

+

*
/
%

14、类型转换
隐式类型转换:
我们要求等号两遍参与运算的操作数的类型必须一致,如果不一致,满足下列条件会发生
自动类型转换,或者称之为隐式类型转换。
两种类型兼容
例如:int 和 double 兼容(都是数字类型)
目标类型大于源类型
例如:double > int 小的转大的

显示类型转换:
1、两种类型相兼容 int–double
2、大的转成小的 double—-int
语法:
(待转换的类型)要转换的值;

总结:
自动类型转换:int—->double
显示类型转换:double—>int

20平
20平 4 5平

Day 3

1、类型如果相兼容的两个变量,可以使用自动类型转换或者强制类型转换,
但是,如果两个类型的变量不兼容,比如 string与int或者string 与double,
这个时候我们可以使用一个叫做Convert的转换工厂进行转换。
注意:使用Convert进行类型转换,也需要满足一个条件:
面儿上必须要过的去。

2、算数运算符
++:分为前++和后++,不管是前++还是后++,最终的结果都是给这个变量加一。
区别表现表达式当中,如果是前++,则先给这个变量自身加一,然后带着这个加一后的值去参与运算。
如果是后++,则先拿原值参与运算,运算完成后,再讲这个变量自身加一。
–:同上。

3、
对于向加加或者减减这样只需要一个操作数就能完成的运算,我们称之为一元运算符。
+ - * / % 对于这些需要两个或以上才能完成运算的操作符,我们称之为二元运算符。
一元运算符的优先级要高于二元运算符。
如果在一个表达式当中,既有一元运算符,又有二元运算符,我们首先计算一元运算符。

int number=10;
int result=10 + ++number;

4、关系运算符
>
<

=

<=

!=
关系运算符是用来描述两个事物之间的关系
由关系运算符连接的表达式称之为关系表达式。
5、bool类型
在c#中我们用bool类型来描述对或者错。
bool类型的值只有两个 一个true 一个false

6、逻辑运算符
&& 逻辑与
||逻辑或
!逻辑非
由逻辑运算符连接的表达式叫做逻辑表达式

逻辑运算符两边放的一般都是关系表达式或者bool类型的值。
5>3 &&true

3>5||false

!表达式
逻辑表达式的结果同样也是bool类型

7、复合赋值运算符
int number=10;
+= :
number+=20;
number=number+20;
-=
number-=5;
number=number-5;
*=
number*=5;
number=number*5;
/=
%=

中级程序员 –2年 —高级程序员—->小组组长—> 项目经理
业务经理
产品经理
高级程序员
不明觉厉
软件开发工程师

顺序结构:程序从Main函数进入,从上到下一行一行的执行,不会落下任何一行。
分支结构:if if-else
选择结构:if else-if switch-case
循环结构:while do-while for foreach

8、
if语句:
语法:
if(判断条件)
{
要执行的代码;
}
判断条件:一般为关系表达式或者bool类型的值。
执行过程:程序运行到if处,首先判断if所带的小括号中的判断条件,
如果条件成立,也就是返回true,则执行if所带的大括号中的代码,
如果判断条件不成立,也就是返回一个false。则跳过if结构,继续向下执行。

if结构的特点:先判断,再执行,有可能一行代码都不执行
用于一种情况的判断。

9、if-else
语法:
if(判断条件)
{
执行的代码;
}
else
{
执行的代码
}
执行过程:程序执行到if处,首先判断if所带的小括号中的判断条件是否成立,
如果成立,也就是返回一个true,则执行if所带的大括号中的代码,
执行完成后,跳出if-else结构。
如果if所带的小括号中的判断条件不成立,也就是返回一个false,
则跳过if语句,执行else所带的大括号中的语句,执行完成后,跳出if-else结构。

if-else特点:先判断,再执行,最少都要执行一条代码。
用于两种情况的判断

注意:else永远跟离它最近的那个if配对

10、if else-if
作用:用来处理多条件的区间性的判断。
语法:
if(判断条件)
{
要执行的代码;
}
else if(判断条件)
{
要执行的代码;
}
else if(判断条件)
{
要执行的代码;
}
else if(判断条件)
{
要执行的代码;
}
……..
else
{
要执行的代码;
}
执行过程;程序首先判断第一个if所带的小括号中的判断条件,如果条件成立,也就是返回一个true,
则执行该if所带的大括号中的代码,执行完成后,立即跳出if else-if结构。
如果第一个if所带的判断条件不成立,也就是返回一个false,则继续向下进行判断,依次的判断每一个if所带
的判断条件,如果成立,就执行该if所带的大括号中的代码,如果不成立,则继续向下判断,
如果每个if所带的判断条件都不成立,就看当前这个if else-if结构中是否存在else。
如果有else的话,则执行else中所带的代码,如果没有else,则整个 if-else if神马都不做。
else可以省略。

Day 4

1、异常捕获
我们在程序中经常会出现各种各样的异常,你如果想要你的程序变得坚强一些。
在你的代码中应该经常性的使用try-catch来进行异常捕获。

哪行代码有可能出现异常,你就踹它一脚。
语法:
try
{
可能会出现异常的代码;
….


}
//try和catch之间不能有其他的代码
catch
{
出现异常后要执行的代码;
}

执行过程:如果try中的代码没有出现异常,那么catch中的代码不会执行。
如果try中的代码出现了异常,那怕这行出现异常的代码后面还有一百行都不会执行了,
而是直接跳到catch中执行代码

2、变量的作用域
变量的作用域就是你能够使用到这个变量的范围。
变量的作用域一般从声明它的那个括号开始到那个括号所对应的结束的括号结束。
在这个范围内,我们可以访问并使用变量。超出这个范围就访问不到了

3、switch-case
用来处理多条件的定值的判断。
语法:
switch(变量或者表达式的值)
{
case 值1:要执行的代码;
break;
case 值2:要执行的代码;
break;
case 值3:要执行的代码;
break;
……….
default:要执行的代码;
break;
}
执行过程:程序执行到switch处,首先将括号中变量或者表达式的值计算出来,
然后拿着这个值依次跟每个case后面所带的值进行匹配,一旦匹配成功,则执行
该case所带的代码,执行完成后,遇到break。跳出switch-case结构。
如果,跟每个case所带的值都不匹配。就看当前这个switch-case结构中是否存在
default,如果有default,则执行default中的语句,如果没有default,则该switch-case结构
什么都不做。

4、循环结构
while循环:
while(循环条件)
{
循环体;
}
执行过程:程序运行到while处,首先判断while所带的小括号内的循环条件是否成立,
如果成立的话,也就是返回一个true,则执行循环体,执行完一遍循环体后,再次回到
循环条件进行判断,如果依然成立,则继续执行循环体,如果不成立,则跳出while循环。
在while循环当中,一般总会有那么一行代码,能够改变循环条件,使之终有一天不再成立,
如果没有那么一行代码能够改变循环条件,也就是循环条件永远都成立,我们称之这种循环
叫做死循环。
最简单的最常用的死循环:
while(true)
{

}

特点:先判断,再执行,有可能一遍循环都不执行。

5、break
1)、可以跳出switch-case结构。
2)、可以跳出当前循环。
break一般不单独的使用,而是跟着if判断一起使用,表示,当满足某些条件的时候,就不再循环了。

6、do-while循环。
语法:
do
{
循环体;
}while(循环条件);
执行过程:程序首先会执行do中的循环体,执行完成后,去判断do-while循环的循环条件,
如果成立,则继续执行do中的循环体,如果不成立,则跳出do-while循环。
特点:先循环,再判断,最少执行一遍循环体。

Day 5

1、*程序调试
1)、写完一段程序后,想看一下这段程序的执行过程。
2)、当你写完这段程序后,发现,程序并没有按照你想象的样子去执行。

调试方法:
1)、F11逐语句调试(单步调试)
2)、F10逐过程调试
3)、断点调试

2、for循环
语法:
for(表达式1;表达式2;表达式3)
{
循环体;
}
表达式1一般为声明循环变量,记录循环的次数(int i=0;)
表达式2一般为循环条件(i<10)
表达式3一般为改变循环条件的代码,使循环条件终有一天不再成立(i++)。
执行过程:程序首先执行表达式1,声明了一个循环变量用来记录循环的次数,
然后执行表达式2,判断循环条件是否成立,如果表达式2返回的结果为true,
则执行循环体。当执行完循环体后,执行表达式3,然后执行表达式2继续判断循环条件是否成立,
如果成立则继续执行循环体,如果不成立,则跳出for循环。

3、int.TryParse
int.parse
尝试着将一个字符串转换成int类型。

4、三元表达式
语法:
表达式1?表达式2:表达式3;
表达式1一般为一个关系表达式。
如果表达式1的值为true,那么表达式2的值就是整个三元表达式的值。
如果表达式1的值为false,那么表达式3的值就是整个三元表达式的值。
注意:表达式2的结果类型必须跟表达式3的结果类型一致,并且也要跟整个三元表达式的结果类型一致。

Day 6

1、变量类型
int double string char bool decimal
变量的使用规则:先声明再赋值最后使用
int number;
number=10;
number=20;
Console.WriteLine(number);

2、Camel Pascal

3、运算符
赋值运算符:=
复合赋值运算符:+= -= *= /= %= sum+=age; sum=sum+age;
算数运算符: + - * / % ++ –
关系运算符: > < >= <= == !=
逻辑运算符: && || !

4、c#中的语法结构
分支结构:
if if-else
选择结构:
while do-while for

5、常量
声明的常量的语法:
const 变量类型 变量名=值;
什么时候会用到常量?

6、枚举
语法:
[public] enum 枚举名
{
值1,
值2,
值3,
……..
}
public:访问修饰符。公开的公共的,哪都可以访问。
enum:关键字,声明枚举的关键字
枚举名:要符合Pascal命名规范

将枚举声明到命名空间的下面,类的外面,表示这个命名空间下,所有的类都可以使用这个枚举。

枚举就是一个变量类型 ,int–double string decimal.
只是枚举声明、赋值、使用的方式跟那些普通的变量类型不一样。

我们可以将一个枚举类型的变量跟int类型和string类型互相转换。
枚举类型默认是跟int类型相互兼容的,所以可以通过强制类型转换的语法互相转换。
当转换一个枚举中没有的值的时候,不会抛异常,而是直接将数字显示出来。

枚举同样也可以跟string类型互相转换,如果将枚举类型转换成string类型,则直接调用ToString().
如果将字符串转换成枚举类型则需要下面这样一行代码:
(要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型),”要转换的字符串”);
如果转换的字符串是数字,则就算枚举中没有,也会不会抛异常。
如果转换的字符串是文本,如果枚举中没有,则会抛出异常。

7、所有的类型都能够转换成string类型,调用ToString()。

8、结构
可以帮助我们一次性声明多个不同类型的变量。
语法:
[public] struct 结构名
{
成员;//字段
}
变量在程序运行期间只能存储一个值,而字段可以存储多个值。

9、数组
一次性存储多个相同类型的变量。
语法:
数组类型[] 数组名=new 数组类型[数组长度];

*数组的长度一旦固定了,就不能再被改变了

10、冒泡排序:就是将一个数组中的元素按照从大到小或者从小到大的顺序进行排列。
int[] nums={9,8,7,6,5,4,3,2,1,0}; 0 1 2 3 4 5 6 7 8 9
第一趟比较:8 7 6 5 4 3 2 1 0 9 交换了9次 i=0 j=nums.Length-1-i
第二趟比较:7 6 5 4 3 2 1 0 8 9 交换了8次 i=1 j=nums.Length-1-i
第三趟比较:6 5 4 3 2 1 0 7 8 9 交换了7次 i=2 j=nums.Length-1-i
第四趟比较:5 4 3 2 1 0 6 7 8 9 交换了6次 i=3 j=nums.Length-1-i
第五趟比较:4 3 2 1 0 5 6 7 8 9 交换了5次
第六趟比较:3 2 1 0 4 5 6 7 8 9 交换了4次
第七趟比较:2 1 0 3 4 5 6 7 8 9 交换了3次
第八趟比较:1 0 2 3 4 5 6 7 8 9 交换了2次
第九趟比较:0 1 2 3 4 5 6 7 8 9 交换了1次
for(int i=0;i

Path类:操作文件的路径

string str=@”E:\resource\Holograms 240\HoloToolkit-Unity-5.6.2f1\HoloToolkit-Unity-1.5.8.0\README.md”;
//获得文件名——————Path.GetFileName(str);
//获得文件名但不包含扩展名——————Path.GetFileNameWithoutExtension(str);
//获得文件扩展名——————Path.GetExtension(str);
//获得文件所在文件夹的名称——————Path.GetDirectoryName(str);
//获得文件全路径——————Path.GetFullPath(str);
//连接两个字符串作为路径——————PathCombine(@”C:\a\”,”b.txt”);

File类:操作文件

//创建一个文件——————File.Create();
//删除一个文件——————File.Delete();
//复制一个文件——————File.Copy();

8、编码格式
产生乱码的原因就是因为你保存这个文件的编码格式跟你打开这个文件的编码格式不一样。

9、文本文件
拖到txt文件中,还能看得懂的文件就是文本文件。

Day12

1、绝对路径和相对路径
绝对路径:通过给定的这个路径直接能在我的电脑中找到这个文件。
相对路径:文件相对于应用程序的路径。
结论:
我们在开发中应该去尽量的使用相对路径。

* List泛型集合和数组之间可以相互转换
List泛型集合————数组:ToArray();
数组————List泛型集合:ToList();

2、装箱、拆箱
装箱:就是将值类型转换为引用类型。
拆箱:将引用类型转换为值类型。
看两种类型是否发生了装箱或者拆箱,要看,这两种类型是否存在继承关系。

3、将创建文件流对象的过程写在using当中,会自动的帮助我们释放流所占用的资源。

4、实现多态的手段
1)、虚方法
步骤:
1、将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍(override)。

2)、抽象类(abstract)
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。

=====
抽象类特点
1.抽象成员必须标记为abstract,并且不能有任何实现。
2.抽象成员必须在抽象类中。
3.抽象类不能被实例化

4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。

(除非子类也是一个抽象类,则可以不重写)
5.抽象成员的访问修饰符不能是private
6.在抽象类中可以包含实例成员。
并且抽象类的实例成员可以不被子类实现

7.抽象类是有构造函数的。虽然不能被实例化。

8、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。

如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。

======
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

Day 13

1、c#中的访问修饰符
public :公开的公共的
private:私有的,只能在当前类的内部访问
protected:受保护的,只能在当前类的内部以及该类的子类中访问。
internal:只能在当前项目中访问。在同一个项目中,internal和public的权限是一样。
protected internal:protected+internal

1)、能够修饰类的访问修饰符只有两个:public、internal。
2)、可访问性不一致。
子类的访问权限不能高于父类的访问权限,会暴漏父类的成员。

2、设计模式
设计这个项目的一种方式。

3、简单工厂设计模式

4、值类型在复制的时候,传递的是这个值得本身。
引用类型在复制的时候,传递的是对这个对象的引用。

5、序列化:就是将对象转换为二进制
反序列化:就是将二进制转换为对象
作用:传输数据。
序列化:
1)、将这个类标记为可以被序列化的。

6、partial部分类

7、sealed密封类
不能够被其他类继承,但是可以继承于其他类。

8、接口
[public] interface I..able
{
成员;
}

#

//接口中的成员不允许添加访问修饰符,默认就是Public
//接口中的方法不允许有方法体

接口是一种规范。
只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员

为了多态。
接口不能被实例化。
也就是说,接口不能new(不能创建对象)

接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。

(默认为public)
接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。

接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。

接口与接口之间可以继承,并且可以多继承。

接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)

实现接口的子类必须实现该接口的全部成员。

一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。

class MyClass:A,IA{},因为类是单继承的。

显示实现接口的目的:解决方法的重名问题
什么时候显示的去实现接口:
当继承的接口中的方法和参数一摸一样的时候,要是用显示的实现接口

当一个抽象类实现接口的时候,需要子类去实现接口。

Day 14

1、winform应用程序是一种智能客户端技术,我们可以使用winform应用程序
帮助我们获得信息或者传输信息等。

2、属性
Name:在后台要获得前台的控件对象,需要使用Name属性。
visible:指示一个控件是否可见。
Enabled:指示一个控件是否可用。

3、事件:发生一件事情。
注册事件:双击控件注册的都是控件默认被选中的那个事件。
触发事件:

4、
在Main函数当中创建的窗体对象,我们称之为这个窗体应用程序的主窗体。
也就意味着,当你将主窗体关闭后,整个应用程序都关闭了。

5、TextBox控件
WordWrap:指示文本框是否换行。
PasswordChar:让文本框显示一个单一的字符
ScollBars:是否显示滚动条
事件:TextChanged 当文本框中的内容发生改变的时候触发这个事件。

6、跑马灯练习
把字符串最后一个字符截取放到最后,通过Timer控件实现动态效果
abcde
bcdea
string str=”abcde”;
str=str.Substring(1)+str.Substring(0,1);

cdeab
deabc
eabcd
abcde

7、Timer
在指定的时间间隔内做一件指定的事情。
Enable属性:默认为false,需将其改为true
Interval属性:事件发生的频率(以毫秒为单位)
事件Tick:每经过指定的时间间隔,触发事件

8、简单记事儿本应用程序
1)、在程序加载的时候,取消文本框的自动换行,以及让两个按钮和文本框隐藏
2)、点击登陆,判断是否登陆成功
3)、自动换行功能
4)、保存文本到一个指定目录下。

9、单选和多选
checked:指示这个控件是否处于选中状态。

默认情况下,在一个窗体中,所有的单选按钮只允许选中一个,可以使用groupbox进行分组。

10、MDI窗体的设计
1、首先确定一个父窗体。 将IsMdiContainer设置为true。
2、创建子窗体,并且设置他们的父窗体。
Form2 frm2 = new Form2();
frm2.MdiParent = this;
frm2.Show();

Day 20

1、new关键字
1)、创建对象
2)、隐藏从父类那里继承过来的成员

2、访问修饰符
public:公开的,公共的
private:私有的,只能在当前类的内部访问,类中成员们,如果不加访问修饰符,默认就是private
procteced:受保护的,可以在当前类的内部访问,也可以在该类的子类中访问
internal:在当前项目中都可以访问。
protected internal:
能够修饰类的访问修饰符只有两个,internal和public

3、常用的关键字
this
1、当前类的对象
2、调用自己的构造函数
base
调用父类的成员
new
1、创建对象
2、隐藏父类的成员
virtual
标记一个方法是虚方法
abstract
抽象的
override
重写
interface
接口
partial
部分类
sealed
密封类:不允许被继承
return
1、在方法中返回要返回的值
2、立即结束本次方法
break
跳出当前循环
continue
结束本次循环,回到循环条件进行判断
static
静态的
struct
结构
enum
枚举
const
常量

4、字符串
1、字符串的不可变性
2、字符串可以看做是char类型的只读数组

5、集合
ArrayList
Hashtable
List
Dictionary

#

集合内部数据是使用数组进行存储的,一个空的集合内部会有一个长度为0的数组,当给集合中添加元素的时候,
列表的容量会扩大为4,如果添加第5个,集合的大小会重新设置为8,每次一2倍的速度扩容。如果事先知道要存储的数据个数,
就可以利用集合的构造函数指定集合的容量大小,比如下面的
List list=new List(10);创建了一个初始容量为10的集合,当容量不够时,每次都会按照原来容量的两倍进行扩容

我们可以通过Capacity属性获取和设置容量
list.Capacity=100;

集合中元素个数可以通过Count属性获取
lisi.Count

可以通过索引去访问集合中的元素
Console.WriteLine(list[0]);

遍历集合的两种方式:
for循环,遍历所有的索引,通过索引访问集合中的元素
for(int i=0;i

原创粉丝点击