C#基础

1、 课程简介
2、 .net平台&C#语言简介
3、 开发环境与学习资料
4、 Hello World
5、 注释&快捷健
6、 变量&变类型
7、 变量的命名规则&使用规范
8、 赋值运算符&+号的使用
9、 算数运算符
10、 关系运算符&逻辑运算符
11、 占位符&转义符
12、 数据类型转换
13、 数字格式说明符
14、 字符串处理
15、 分支结构一 if
16、 分支结构二 switch
17、 循环结构一 do while
18、 循环结构二for循环
19、?: ? ??
20、数组类型
21、枚举类型
22、类
23、 类成员之字段
24、 类成员之方法
25、 类成员之属性
26、 类成员之索引器
27、命名空间
28、接口
29、静态和非静态
30、值类型和引用类型
31、string和StringBuilder
32、ref和out的应用与区别
33、 is和as的应用
34、隐式类型和初始化器

C#语言简介

1、课程简介

1.1、什么是程序( Program )

为什么需要程序

怎样编写程序和程序语言的选择

●编辑>编译>调试>发布
●编程的学习路径
●纵向:语言→类库>框架
●横向:命令行程序,桌面程序,设备(平板/手机)程序,Web(网站/服务)程序,游戏....

1.2、什么是软件:

1.与计算机系统操作有关的计算机程序、规程、规则,以及可能有的文件、文档及数据。

2.可以分为系统软件和应用软件。

3、软件并不是一定要运行在计算机上的。

特点:
1、无形,没有物理形态。

2.渗透了大量的脑力劳动,人的逻辑思维。

3.不会老化磨损,因为没有物理形态,但是需要定期维护和技术更新。

4、开发和运行需要依赖特定的计算机环境。

5、具备可复用性,容易被复制,形成多个副本。

1.3、为什么需要软件:

1、计算机的普及。

2、提高办公效率。

3.影音娱乐。

4.游戏娱乐。

5.等等....

编写软件有哪些编程语言?

C#,VB, php, C语言,C++, Java, Python, 等等....

编程语言分为几种?

1.汇编语言(直接对硬件进行操作) MASM、NASM、TASM、GAS、FASM、 RADASM等。应用于对时效性要求高的程序,大型程序的核心模块,工业控制方面。

2.脚本语言(为了缩短传统的编写编译链接运行的过程而创建的计算机编程语言)是一-种解释性的语言,例如Python, JavaScript等

3、高级语言(不能直接被计算机识别,需要进行转换)
转换方式可分为两类:解释类,编译类。
解释类:类似于同声翻译,一边被解释器编译成机器语言,一边执行,效率较低,但是灵活。例如: Python, javaScript, Java
编译类:程序执行之前要先进行编译,编译成机器语言后再去执行。缺点是每次修改代码后都要重新进行编译。例如: C, C++,C#

2、.net平台&C#语言简介

.Net:是.Net Framework的简称,它是微软开发的一个框架,是一种平台,一种技术。

.Net是一个平台,也是一个框架,平台承载着框架,框架上运行着软件应用。

编程语言是一门计算机语言,要想让软件能够执行人们的指令,需要通过一种编程语言和计算机通讯

C#,Csharp:是微软开发的一种高级编程语言,只是一种编程语言。可以开发运行于.Net平台 上的应用。在.Net平台上可以使用的还有VB,F#,C++等语言

C#集成了Java和C+ +两门语言的的优点,学习起来简单易学,适合作为入门语言。

桌面应用程序: C/S是Client/Server的缩写。 服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统。客户端需要安装专用的客户端软件。例如QQ,或者Office办公软件。

Web应用程序: B/S是Browser/Server的缩写, 客户机上只要安装个浏览器(Browser) ,服务器安装数据库。在这种结构下,用户界面完全通过WWW浏览器实现,-部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现。浏览器通过Web Server 同数据库进行数据交互。例如,淘宝,京东等购物网站。

两者的区别:
1.硬件环境不同: C/S 一般建立在专用的网络上,小范围里的网络环境; B/S建立在广域网之上的。
2、对安全要求不同: C/S - -般面向相对固定的用户群,对信息安全的控制能力很强; B/S 建立在广域网之上,对安全的控制能力相对弱,
可能面向不可知的用户。
3、对程序架构不同: C/S程序可以更加注重流程,对系统运行速度可以较少考虑: B/S对安全以及访问速度的多重的考虑。
4、开发维护成本
5.客户端负载

3、开发环境与学习资料

●下载Visual Studio ( http://www.visualstudio.com/ )

●安装Visual Studio

●学习资料

●下载离线MSDN文档
●C#语言定义文档( Language Specification )
●推荐书籍: C# 5.0 In A Nutshell

VS是Microsoft Visual Studio的简称。VS是美国微软公司的开发工具包系列产品。

Visual Studio是目前最流行的Windows平台应用程序的集成开发环境。

最新版本为Visual Studio 2019版本,基于.NET Framework 4.6/7。

2002-2019版本

安装VS2017开发工具

勾选帮助文档

VS2017工具各个组成部分:
菜单栏,工具栏,解决方案窗口,属性窗口,错误列表,局部变量,监视窗口等
VS的一些常用设置:行号,字体,背景色等。

4、Hello World

分别使用控制台和窗体应用创建第个Hello World项目。

如何启动项目,启动项目的快捷键。

C#语言的编程语言规则:

必须以分号结束一行。

要使用英文半角输入法编写代码。

C#是一门强类型语言,严格区分大小写。

一个解决方案中有多个项目的时候如何设置启动的项目。

如何卸载和加载其中的某个项目。

C#中的组织结构的关键概念是程序(program).命名空间(namespace).类型(type)、成员(member)和程序集(assembly)。C#程序由一个或多个源文件组成。程序中声明类型,类型包含成员,并且可按命名空间进行组织。
创建项目时需要注意项目名称和解决方案名称的区别,一个解决方案中可以包含多个项目。

VS中有多种类型的项目可供用户进行选择。

项目中包含多个类文件。例如: Properties (属性文件),App.config (配置文件),Program.cs (程序主入口文件)等。

Program.cs,类文件中的代码组成部分:
using,(引用命名空间的关键字)
namespace, (声明命名空间的关键字)
calss, (类的修饰符)

4.1、创建一个控制台项目

4.1.1、

4.1.2、

4.1.3、

4.1.4、

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//使用using关键字,将一些命名空间引入到类文件中
using System.Threading.Tasks;
//自己创建的命名空间 项目名
namespace HelloWorld
{
    class Program //class 是类的修饰符
    {
        //程序入口
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Console.WriteLine("Hello World!");
            Console.WriteLine("Hello World!");

            Console.Write("Hello World!");
            Console.Write("Hello World!");
            Console.Write("Hello World!");
            Console.ReadKey();
        }
    }
}

4.1.5、运行

4.2、创建一个窗体项目

4.2.1、可右击解决方案创建

4.2.2、选择窗体

4.2.3、右击按钮属性test可更改名字

4.2.4、代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsHelloWorld
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello World! ");//显示信息提示框

        }
    }
}

4.2.5、运行

5、注释&快捷键

5.1、注释的三种类型:

1、单行注释:从开始标记到该行行尾的文本被编译器忽略。//
2、带分隔符的注释:从开始标记到结束标记之间的文本被编译器忽略。/* */
3、文档注释:文档注释包含xml文本,可用于产生程序文档。

注释的两种形式:单行注释和带分隔符的注释。

1.单行注释以字符//开头并延续到源行的结尾。

2、带分隔符的注释以字符/* 开头,以字符 / 结束。带分隔符的注释可以跨多行。
注释不嵌套。字符序列/
/在//注释中没有任何特殊含义,字符序列/和/在带分隔符的注释中没有任何特殊含义。在字符和字符串内不处理注释。
文档注释:
///


///这里是对文档的注释内容
///

5.2、VS常用快捷键:

Ctrl+J 自动补全代码

Ctrl+K+ D 格式化代码,代码对齐

Ctrl+K+C 注释所选代码

Ctrl+K+U 取消注释代码

Ctrl+Z 撤销

Ctrl+S保存(一定定要养成有事儿没事儿按下保存的好习惯)。

选中+F1 打开帮助文档

do+两次Tab 代码片段

5.3、#Region折叠代码块

6、变量&变类型

​ C#中的类型有两种:值类型(value type)和引用类型(reference type)。值类型的变量直接包含它们的数据,而引用类型的变量存储对它们的数据的引用,后者称为对象。对于引用类型,两个变量可能引用同一一个对象,因此对一一个变量的操作可能影响另-个变量所引用的对象。对于值类型,每个变量都有它们自己的数据副本(除ref和out参数变量外),因此对一一个变量的操作不可能影响另一个变量。

​ C#的值类型进一步划分为简单类型(simple type).枚举类型(enum type).结构类型(struct type)和可以为null的类型(nullable type), C#的引用类型进一步划分为类类型(class type).接口类型(interface type)、数组类型 (array type)和委托类型(delegate type)。

变量:用于在计算机中存储数据,变量名代表内存中的一个存储单元,在对程序编译连接的时候由系统给变量分配一个地址。
在程序中从变量中取值,实际上是通过变量名找到相应的内存单元,从其中读取数据。

声明变量的语法:
变量类型变量名;
变量赋值(初始化)
变量名=值:

值类型

简单类型

有符号整型: sbyte. short. int. long
无符号整型: byte. ushort. uint. ulong

字符型: char

浮点型: float. double
高精度小数型: decimal

 static void Main(string[] args)
        {
            int age;
            age = 18;//等号赋值运算符
            Console.WriteLine(age);//变量在使用前必须要先赋值也叫初始化
            Console.ReadKey();

            float fl = 3.50F;
            double du = 3.5;
            decimal de = 3.5M;
            char ch = 'x';//char型的 有且并且要有且只能有一一个字符
            string str ="老师说这里可以存储无限长度的文本";
            string name, className; 
        }

布尔型: bool

枚举类型enum E {...}形式的用户定义的类型

结构类型struct S {...}形式的用户定义的类型

可以为null的类型

其他所有具有null值的值类型的扩展

引用类型

类类型

所有其他类型的最终基类: object

字符串: string

class C {...}形式的用户定义的类型

接口类型interface I {...}形式的用户定义的类型

数组类型一维和多维数组,例如int]和int[]

委托类型delegate int D(..)形式的用户定义的类型

7、变量的命名规则&使用规范

变量的使用规则:
1、先声明变量。
2、再给变量赋值。
3、然后再使用变量。
注意:不赋值则无法使用

命名规则:
首字符必须以字母或者@符或者下划线开始。
后面的字符可以是字母,数字或下划线
系统保留的关键字,不可以作为变量名来使用。

命名规范:
camel命名法:首单词首字母小写,后面的单词首字母大写。
多用于简单变量的命名中
Pascal命名法:首单词首字母大写,后面的单词首字母大写。
多用于属性,函数,类,项目等等的命名。

变量的作用范围:
以最近的大括号开始,到对应的大括号结束
红色波浪线表示语法错误,编译器无法完成编译,可以在下面的错误列表中找到错误原因。
绿色波浪线表示警告错误

8、赋值运算符&+号的使用

简单赋值运算符: =
等号表示赋值的意思,将等号右边的值,赋给等号左边的变量。
由等号连接的表达式称之为赋值表达式。
复合赋值运算符:
1、+=

2、-=

3、*=

4、1=

5、%=

int age = 18;
            int x = 1,y = 2,z = 3;
            z += x;//z=z+x;
            Console.WriteLine(z);
            Console.ReadKey();

加号: +
1、相加:可以作为计算加法的加号
2、相连接:连接两个字符串,加号两边任一边有字符串, 即为相连接。
intx = 10;
x=20;
Console.WriteLine(x);
此时输出多少?
小栗子:做个自我介绍
我叫什么,我来自哪里,今年多少岁,身高多少,体重多少,现在居住在哪里。

string name = "小明";
            string from = "山东";
            int age = 18;
            int height = 180;
            float weight = 70.5f;
            string addr = "江苏";
            //"我叫name,我来自from,今年age岁, 身鳥heightCM, 体重weightKG, 现在居住在addr";
            string str = "我叫"+name+",我来自"+from + ",今年 "+age+"岁,身高" + height +
              "CM,体重"+ weight + "KG,现在居住在"+addr;
            Console.WriteLine(str);
            Console.ReadKey();

9、算数运算符

算数运算符:
+:相加x+y
相减x-y

:相乘 xy
/:相除x/y
%:取余x%y
运算先后顺序:先一元后元;先乘除后加减;先括号内再括号外。
++自加运算符,
-自减运算符。

++或--放在变量的左右是一样的,但在表达式中会有变化
++在左,先自增后返回,
++在右,先返回后自增,
--在左,先自减后返回,
--在右,先返回后自减。

10、关系运算符&逻辑运算符

关系运算符:又称为比较运算符,用来描述两个事物之间的关系,其连接的表达式称之为关系表达式
常用关系运算符有:

<; >; <=; >=; ==; !=;

条件逻辑运算符:

&& 逻辑与(要求使用&&连接起来的关系表达式全部成立的时候,才会返回个True,只要有一个是False, 则会返回False)

**|| ** 逻辑或(只要多个关系表达式中有一个返回值是True,则整个逻辑表达式的返回值是True。全部都是False的话,才会返回False)

**! ** 逻辑非 (取关系表达式的返回结果或者是Bool结果的相反的值

逻辑运算符连接的表达式叫做逻辑表达式。

逻辑运算符两边放的一般是关系表达式或者Bool型的值(Bool类型只有两个值,True和False)

11、占位符&转义符

拼接字符串的方式: +号、占位符。

 string str = string.Format("我叫{0},我来自{1},今年{2}岁,身高{3}CM,体重{4}KG,现在居住在{5}",
"小明", "山东", 18, 180, 70.5, "山东");

什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号。
占位符可以少占,多填。但是不可以多占,少填。
转义符分为两种:一种是,一种是@。
@两个作用:取消转义符:使用系统关键字。
字符@只能对字符创常量起作用。
使用@表示字符串能够跨越行数,用于SQL, JS等。

  string @string = @"
    离离原上草,
        一岁一枯荣,
            野火烧不尽,
                春风吹又生。";

            Console.WriteLine(@string);
            Console.ReadKey();

放在标识符前面,可以使用系统关键字,但是不作为标识符本身的一部分。例如@Class @String
Y'单引号"双引号
1反斜杠 Tab键
退格
f换页
换行
回车
水平制表v垂直制表(零)空字符

12、数据类型转换

隐式转换:从类型A到类型B的转换可在所有情况下进行,执行转换的规则非常简单,可以让编译器执行转换。
隐式转换不需要做任何工作,也不需要另外编写代码。
隐式数值转换为:
从sbyte到short. int, long. float. double或decimal.
从byte到short, ushort, int, uint. long. ulong. float, double 或decimal.
从short到int, long. float. double 或decimal.
从ushort到int. uint. long. ulong. float. double 或decimal.
从int到long. float, double 或decimal.
从uint到long. ulong. float, double 或decimal。
从long到float. double或decimal.
从ulong到float. double 或decimal.
从char到ushort, int. uint. long. ulong. float, double 或decimal.
从float到double。

显式转换:从类型A到类型B的转换只能在某些情况下进行,转换规则比较复杂,应进行某种类型的额外处理。
顾名思义,在明确要求编译器把数值从一种数据类型转换为另 -种数据类型时,就是在执行显式转换。因此,这需要另外编写代码,代码的格式因转换方法而异。
使用Convert命令进行显式转换。

13、数字格式说明符

常见常用标准数字格式说明符

14、字符串处理

1、ToCharArray() 将此实例中的字符复制到字符数组

2、Length获取并返回当前字符串中字符的数量(Length属性)

3、ToLower()和ToUpper()转换成小写和大写

4、Trim()去除两端的空格或者指定的字符(去开头或去结尾)

5、TrimStart(和TrimEnd()命令, 它们可以把字符串前面或后面的空格删掉

6、string .PadLeft()和string.PadRight(.它们可以在字符串的左边或右边添加空格,使字符串达到指定的长度

7、Equals 比较两个字符串是否相等。Equals(String) Equals(String, String)

8、IndexOf()报告指定字符或字符事在此字符串中的第一个匹配项的索引。

9、Insert() 在此实例中的指定索引位置插入一个指定的String实例

10、IsNullOrEmpty()指示指定的字符串是null还是Empty字符串

11、IsNullOrWhiteSpace()指示指定的字符串是null. 空还是仅由空白字符组成

12、LastIndexOf()指定字符或字符串在此实例中的最后一个匹配项的索引位置
13、 Remove()删除此字符串中从指定位置到最后位置的所有字符


从第3个移除移除了2个

14、 Replace() 返回一个新字符串,其中当前实例中出现的所有指定字符串都替换为另一个指定的字符串


指定字符串替换成e

15、Substring()截取字符串或者截取指定长度的字符串


从第5个截取,截取2个

16、String.Format
将指定字符串中的每个格式项替换为相应对象的值的等效文本。
静态的Format方法提供了创建嵌入变量字符串的便利方法。嵌入的变量可以是任意类型; 而Format 会直接调用它们的ToSting.

17、StringBuilder
StringBuilder类(System.Text命名空间) 表示个可变(可编辑)的字符串。使用StringBuilder,可以Append、Insert. Remove和Replace子字符串,而不需要替换整个StringBuilder.
StringBuilder的个普遍使用方法是通过重复调用Append来创建一个长字符串。这个方法比复杂连接普通字符串类型要高效得多。

15、分支结构一if

分支结构:分支是控制下一步要执行哪行代码的过程。要跳转到的代码行由某个条件语句来控制。这个条件语句使用布尔逻辑,对测试值和一个或多个可能的值进行比较。
if语句: if语句的功能比较多,是有效的决策方式。if语句最简单的语法如下:
if ()
<code executed if is true>;
先执行 (其计算结果必须是一个布尔值,这样代码才能编译),如果的计算结果是true,就执行该语句之后的代码。这段代码执行完毕后,或者因为的计算结果是false,而没有执行这段代码,将继续执行后面的代码行。也可将else语句和if语句合并使用,指定其他代码。如果的计算结果是false,就执行else语句:
if ()
<code executed if is true>;
else
<code executed if is false>;
可使用成对的花括号将这两段代码放在多个代码行上:
if ()
<code executed if is true>;
else
<code executed if is false>;

16、分支结构二switch

例题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace demo03
{
    class Program
    {
        static void Main(string[] args)
        {
            int week;

            while (true)
            {
                Console.WriteLine("请输入数字:");
                int.TryParse(Console.ReadLine(), out week);//用户输入的值
                if (week > 0)
                {
                    switch (week)
                    {
                        case 1:
                            Console.WriteLine("星期一");
                            break;
                        case 2:
                            Console.WriteLine("星期二");
                            break;
                        case 3:
                            Console.WriteLine("星期三");
                            break;
                        case 4:
                            Console.WriteLine("星期四");
                            break;
                        case 5:
                            Console.WriteLine("星期五");
                            break;
                        case 6:
                            Console.WriteLine("星期六");
                            break;
                        case 7:
                            Console.WriteLine("星期七");
                            break;
                        default:
                            Console.WriteLine("请输入1-7的数字");
                            break;
                    }
                }
                else {
                    Console.WriteLine("请输入正确的数");
                }
            }
           
        }
    }
}

结果

小结

随堂小结:
switch分支结构,case后面是一个常量,并且是用冒号结束。case 下面代码执行完毕,必须要有break
default语句是不是必须要有的,如果前面的case都无法满足条件匹配,则最好有一个default语句来处理
ReadLine(用来接收用户在控制台上输入的数据

if与switch的区别

if(布尔值)不符合跳出,switch(各种类型)以下都匹配

17、循环结构一do while

循环就是重复执行语句。这个技术使用起来非常方便,因为可以对操作重复任意多次(数干次,甚至数百万次),而不必每次都编写相同的代码。循环的另一种重要类型是一直循环到给定的条件不满足为止结束。
do循环
do循环以下述方式执行:执行标记为循环的代码,然后进行一一个布尔测试,如果测试结果为true,就再次执行这段代码,并重复这个过程。当测试结果为false时,就退出循环。
do循环的结构如下:
do

while ();
其中,计算会得到一个布尔值。

while循环
非常类似于do循环,但有一个明显区别: while循环中的布尔测试在循环开始时进行,而不是最后进行。如果测试结果为false,就不会执
行循环。程序会直接跳转到循环之后的代码。
while ()

{}

小结:
do循环,while循环
区别: do循环是先执行循环体中的代码,再进行条件判断,条件为True的话则继续执行循环体。
while循环先判断条件,条件为True的话再执行循环体。
死循环:条件一直成立,无限循环下去。

18、循环结构二 for循环

for循环
这类循环可以执行指定的次数,并维护它自己的计数器。要定义for循环,需要下列信息:τ
1.初始化计数器变量的一个起始值。
2、继续循环的条件,应涉及计数器变量。
3、在每次循环的最后,对计数器变量执行一个操作。
如下所示:
for (;;)
{

Foreach循环

循环的中断

有时需要更精细地控制循环代码的处理。C#为此提供了以下命令:
break--立即终止循环。
continue立 即终止当前的循环(继续执行下一次循环)。

return--跳出循环及包含该循环的函数

小结:
for循环,先初始化计数器(初始化语句只在循环开始的时候执行一次),再进行条件判断,条件成立的话,然后执行循环中的代
码段,执行结束后,计数器进行操作。
foreach使用in关键字,条件自动满足,不需要手动设置循环次数。
跳出循环: break 跳出循环体。continue 终止当前循环,直接执行下一次循环。

循环嵌套

使用哪个循环?
while
do while
for
学习使用嵌套循环
for(inti= 0;i< n; i++)
{
for(intj= 0;j< m;j++)
}
嵌套循环:外层循环执行一次,内层循环执行完整次数。

打印九九乘法表

static void Main(string[] args)
        {
            for (int i = 1; i < 10; i++)
            {
                for (int j = 1; j <= i; j++)
                {
                    Console.Write("{0}*{1}={2} 	", j, i, i * j);
                }
                Console.WriteLine();
            }
            Console.ReadKey();

        }

19、?: ? ??

?:条件运算符或三元运算符
其语法如下:
?:
b?x:y形式的条件表达式首先计算条件b。然后,如果b为true,则将计算x,并且它将成为运算结果。否则计算y,并且它成为运算结果。条件表达式从不同时计算x和y。
条件运算符向右关联,表示运算从右到左分组。例如,a ?b:c?d:e形式的表达式可以按a?b:(c ?d: e)进行计算。
?:运算符的第一个操作数必须是可以隐式转换为bool 的表达式,或是实现operator true的类型的表达式。如果两个要求都不满足,则发生编译时错误。
与if语句不同的是,if语句没有结果(所以不在赋值语句中使用它)。使用该语句是为了根据条件执行其他语句。

?可空修饰符
若要在数值类型中表示空值,必须使用特殊的结构即可空类型 (Nullable) 。可空类型是由数据类型 后加一个“?”表示的:
int? = null;

int? age, x = null, y = 3, z = 5;//允许为空   

??运算符称为空合并运算符
a ?? b形式的空合并表达式要求a为可以为null的类型或引用类型。如果a为非null,则a ?? b的结果为a;否则,结果为b。仅当a为null时,该操作才计算b。

int? age, x = null, y = 3, z = 5;//允许为空   
age = x ?? x ?? x ?? x ?? z ?? y ?? z;//遇到第一个为空的值停止输出,结果为5

空合井运算符为右结合运算符,表示操作从右向左进行组合。例如,a ?? b??c形式的表达式可以按a?? (b ?? c)进行计算。概括地说,E1 ?? E2 ?? ... ?? EN形式的表达式返回第一个非null的操作数,如果所有操作数都为null,则返回null.

20、数组类型

数组类型:

之前讲的类型有一个共同点:它们都只存储一个值。有时,需要存储许多数据,这样就会带来不便。有时需要同时存储几个类型相同的值,而不想为每个值使用不同的变量。
数组是一个变量的索引列表,存储在数组类型的变量中。在方括号中指定索引,即可访问该数组中的各个成员。这个索引是一个整数,第一个条目的索引是0,第二个条目的索引是1,依此类推。
数组有一个基本类型,数组中的各个条目都是这种类型。
以下述方式声明数组:

O;
其中, 可以是任何变量类型,包括枚举和结构类型,数组必须在访问之前初始化。
数组的初始化有两种方式。可以字面值形式指定数组的完整内容,也可以指定数组的大小,再使用关键字new初始化所有数组元素。
要使用字面值指定数组,只需提供一个用逗号分隔的元素值列表,该列表放在花括号中,例如: int[] myIntArray={5,9, 10,2,99 };其中,myIntArray有5个元素,每个元素都被赋予-个整数值。

另一种方式需要使用下述语法: int[] myIntArray = new int[5];
这里使用关键字new显式地初始化数组,用个常量值定义其大小。这种方式会给所有数组元素赋予同一一个默认值,对于数值类型来说,其默认值是0。

也可以使用非常量的变量来进行初始化,例如: int0 myIntArray = new int[arraySize];
还可以组合使用这两种初始化方式: int] myIntArray= new int[5] {5, 9, 10, 2, 99 }:使用这种方式,数组大小必须与元素个数相匹配。

二维数组

int[,] age = new int[3, 6]{ { 11,12,13,14,15,16},{ 21,22,23,24,25,26},{31,32,33,34,6,12}};
Console.WriteLine(age[1, 2]);//结果为23

21、枚举类型

它们允许定义一个类型,其取值范围是用户提供的值的有限集合。
不是仅声明一个给定类型的变量,而是声明和描述一个用户定义的类型, 再声明这个新类型的变量。
定义枚举
用enum关键字定义枚举,如下所示:
enum
,
,
,

接着声明这个新类型的变量:
;
并赋值:
= .;
枚举使用一个基本类型来存储。枚举类型可取的每个值都存储为该基本类型的一个值,默认情况下该类型为int.
枚举的基本类型可以是byte. sbyte. short. ushort. int. uint. long和ulong.

namespace demo05
{
    class Program
    {
        enum weekDay
        {
            Mon=1,
            Tus,
            Wed,
            Thu,
            Fri,
            Sat,
            Sun
        }
        static void Main(string[] args)
        {
            foreach (int val in Enum.GetValues(typeof(weekDay)))
            {
                Console.WriteLine(Enum.GetName(typeof(weekDay) , val));
                Console.WriteLine(val);

            }
            Console.ReadKey();
        }
    }
}

22、

​ 用3个关键字可以标记出能处理异常的代码和指令,如果发生异常,就使用这些指令处理异常。用于这个目的的3个关键字是try. catch和finaly.它们都有一个关联的代码块,必须在连续的代码行中使用。其基本结构如下:
try
{
}
catch ( e) when filterlsTrue)
<await methodName(e);>
finally
{

也可以只有try块和finally块,而没有catch块, 或者有一个try块和好几个catch块。如果有一个或多个catch块,finally块就是可选的, 否则就是必需的。这些代码块的用法如下:
try--包含抛出异常的代码 (在谈到异常时,C#语言用“抛出”这个术语表示“生成”或“导致”)。
catch--包含抛出异常时要执行的代码。 catch块可以使用.设置为只响应特定的异常类型。
finally---包含始终会执行的代码, 如果没有产生异常,则在try块之后执行,如果处理了异常,就在catch块后执行。(如果没有catch块,就一定要有finally块) 。

代码

namespace demo06
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] age = { 16, 17, 18, 19, 20 };
            while (true)
            {
                int index = int.Parse(Console.ReadLine());
                try
                {
                    Console.WriteLine(age[index]);
                }

                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            Console.ReadKey();
        }
    }
}

自定义异常

22、类

C#使用class关键字来定义类:
class MyClass
{
“Class members.
这段代码定义了一一个类MyClass.定义了一个类后,就可以在项目中能访问该定义的其他位置对该类进行实例化。默认情况下,类声明为内部的,即只有当前项目中的代码才能访问它。
另外,还可以指定类是公共的,可由其他项目中的代码来访问。为此,要使用关键字public:
public class MyClass
" Class members.

访问修饰符的含义
1、无或internal (内部的) 只能在当前项目中访问类

2、public (公共的) 可以在任何地方访问类

3、abstract (抽象的) 类只能在当前项目中访问,不能实例化,只能被继承
public abstract类可以在任何地方访问,不能实例化,只能被继承
4、Sealed (密封的) 或internal sealed类只能在当前项目中访问,不能被继承,只能实例化
public sealed类可以在任何地方访问,不能被继承,只能实例化

构造函数:
在C#中定义类时,常常不需要定义相关的构造函数,因为在编写代码时,如果没有提供它们,编译器会自动添加它们。

抽象类:
抽象类就是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。
抽象类可以拥有抽象成员(没有代码体,且必须在派生类中实现,否则派生类本身必须也是抽象的)和非抽象成员(它们拥有代码体,也可以是虚拟的,这样就可以在派生类中重写)。

密封类:
密封类和抽象类相反。
只能被用作独立的类,它不能被用作基类;
密封类使用sealed修饰符声明。

静态类:
类的所有成员必须是静态的;
静态类是隐式密封的,也就是说不能继承静态类。
静态类使用static修饰符声明。

类的继承:
通过继承可以定义一个新类,新类纳入一个已经声明的类并进行扩展。
可以使用一一个已经存在类作为新类的基础。已经存在的类称为基类,新类称为派生类,派生类的成员组成为本身声明中的成员以及基类的成员;要声明一个派生类,需要在类名后加入基类规格说明,基类规格说明是由冒号和后面跟着的用作基类的类名称组成;派生类扩展它的基类,因为它包含了基类的成员,加上在它本身声明中的新增功能:派生类不能删除它所继承的任何成员。

小结:

abstract想象成一个模子,比如银行必须有存款,取款

静态类无法被实例化,直接类.成员变量即可

23、类成员之字段

字段(field)是一种表示与对象或类关联的变量的成员。
用标准的变量声明格式(可以进行初始化)和修饰符来定义字段,例如:
class MyClass
public int MyInt;
注意: .NET Framework中的公共字段以PascalCasing形式来命名, 而不是camelCasing.这里使用的就是这种大小写形式,所以上面的字段称为MyInt而不是mylnt,这仅是推荐使用的一种名称大小写形式,但它的意义非常重大。私有字段没有推荐的名称大小写模式,它们通常使用camelCasing来命名。
静态字段和实例字段:
当一个字段声明中含有static修饰符时,由该声明引入的字段为静态字段(static field)。 当不存在static修饰符时,由该声明引入的字段为instance fields。 静态字段和实例字段是C#所支持的几种变量中的两种,它们有时被分别称为静态变量(static variable)和实例变量(instance variable)。

只读字段:
当一个字段声明中含有readonly修饰符时,该声明所引入的字段为只读字段(readonly field)。 给只读字段的直接赋值只能作为声明的组成部分出现

小结:
字段:公共字段命名和私有字段命名的规范。
静态成员,实例成员:静态成员使用static修饰符,实例成员不需要。
只读的字段readonly,只能在构造函数中赋值或者是在字段初始化的时候赋值。

使用访问权限修饰符,通过实例化访问了,这个变量就认为是一个字段了

当变量有了new关键字后就是一个对象了

24、类成员之方法

方法是具有名称的可执行代码块,可以从程序的很多不同地方执行,甚至从其他程序中执行。当方法被调用时,它执行自己所包含的代码,然后返回到调用它的代码并继续执行调用代码下面的代码段。有些代码会返回一个值到他们被调用的位置。

静态方法和实例方法
若一个方法声明中含有static 修饰符,则称该方法为静态方法。若其中没有static 修饰符时,则称该方法为实例方法。

方法重载
函数重载允许创建多个同名函数,每个函数可使用不同的参数类型。

virtual--方法可以重写。
abstract---方法必须在非抽象的派生类中重写 (只用于抽象类中)。

override--方法重写了 一个基类方法(如果方法被重写,就必须使用该关键字)。


1

小结:
标记方法可以被重写: virtual(不一定重写)
标记方法必须被重写,用在抽象类中:abstract(必须重写所有方法,强制性)
重写方法: override

例题

达成效果:
用户输入一门成绩,然后根据成绩来判断是什么等级的。
用户输入两门成绩,然后根据成绩来判断是什么等级的。
用户输入三门成绩,然后根据成绩来判断是什么等级的。
提示用户输入哪门成绩
提示用户需要输入数字
输出等级信息

namespace test01
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                int x, y, z;
                Student stu = new Student();
                Console.WriteLine("请选择输入几科成绩: 
1是仅-科成绩
2是有两科成绩
3是有三科成绩");
                string index = Console.ReadLine();
                switch (index)
                {
                    case "1":
                        Console.WriteLine("清输入-门成绩: ");
                        x = int.Parse(Console.ReadLine());
                        Console.WriteLine("成绩的等级是: {0}", stu.Lvl(x));
                        break;
                    case "2":
                        Console.WriteLine("请输入两门成绩: ");
                        x = int.Parse(Console.ReadLine());
                        y = int.Parse(Console.ReadLine());
                        Console.WriteLine("成绩的等级是: {0}", stu.Lvl(x, y));
                        break;
                    case "3":
                        Console.WriteLine("请输入三门成绩: ");
                        x = int.Parse(Console.ReadLine());
                        y = int.Parse(Console.ReadLine());
                        z = int.Parse(Console.ReadLine());
                        Console.WriteLine("成绩的等级是: {}", stu.Lvl(x, y, z));
                        break;
                        Console.ReadKey();
                }
            }

        }
        class Student
        {
            public string Lvl(int x)
            {
                if (x >= 90)
                {
                    return "A";
                }
                else if (x >= 60 && x < 90)
                {
                    return "B";
                }
                else
                {
                    return "C";
                }

            }


            public string Lvl(int x, int y)
            {
                if (x + y >= 180)
                {
                    return "A";
                }
                else if (x + y >= 120 && x + y < 180)
                {
                    return "B";
                }
                else
                {
                    return "C";
                }
            }


            public string Lvl(int x, int y, int z)
            {
                if (x + y + z >= 270)
                {
                    return "A";
                }
                else if (x + y + z >= 180 && x + y + z < 270)
                {
                    return "B";
                }
                else
                {
                    return "C";
                }
            }
        }
    }
}

结果

25、类成员之属性

属性(property)是-种用于访问对象或类的特征的成员。属性是字段的自然扩展,此两者都是具有关联类型的命名成员,而且访问字段和属性的语法是相同的。
属性定义方式与字段类似,但包含的内容比较多。如前所述,属性比字段复杂,因为它们在修改状态前还可以执行-些额外操作,实际上,它们可能并不修改状态。属性拥有两个类似于函数的块,-个块用于获取属性的值,另-个块用于设置属性的值。
这两个块也称为访问器,分别用get和set关键字来定义, 可以用于控制属性的访问级别。可以忽略其中的一个块来创建只读或只写属性(忽略get块创建只写属性,忽略set块创建只读属性)。
属性的基本结构包括标准的可访问修饰符(public. private等) ,后跟属性名和get块(或set块, 或者get块和set块,其中包含属性处理
代码),例如:
public int MyIntProp
get
// Property get code.
}
set
" Property set code.

namespace demo07
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student();
            stu.Age = 20;
            int age = stu.Age;
            stu.Name = "XiaoMing";
            Console.WriteLine(stu.Age);
            Console.ReadKey();
        }
    }
    class Student
    {
        private int age;
        public int Age

        {
            get { return age; }
            set { age = value > 18 ? 18 : value; }
        }

        private string name;
        public string Name

        {
            get { return name; }//读
            set { name = value; }//写
        }
         //prop+Tab*2
        public int MyProperty { get; set; }
        //第二种写法
        //public string Name { set; get; }


    }
}

26、类成员之索引器

索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写.
C#中的类成员可以是任意类型,包括数组和集合。当个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作。

定义索引器的方式与定义属性有些类似,其-般形式如下:
[修饰符]数据类型this[索引类型index]
{
get{/获得属性的代码}
set{ //设置属性的代码}

修饰符包括public,protected,private,internal,new,virtual,sealed,override,abstract,extern.
数据类型是表示将要存取的数组或集合元素的类型。
索引器类型表示该索引器使用哪一类型的索引来存取数组或集合元素, 可以是整数,可以是字符串; this表示操作本对象的数组或集合成员,可以简单把它理解成索引器的名字,因此索引器不能具有用户定义的名称。

属性和索引器差别:
1.类的每一个属性都必须拥有唯一-的名称,而类里定义的每一个索引器都必须拥有唯一-的签名(signature) 或者参数列表(这样就可以实现索引器重载)。
2.属性可以是static (静态的)而索引器则必须是实例成员。
3.为索引器定义的访问函数可以访问传递给索引器的参数,而属性访问函数则没有参数。

索引器和数组的区别:
索引器能使用非数值下标,而数组只能使用整数下标。
索引器能重载,数组则不能。

namespace demo09
{
    class Program
    {
        static void Main(string[] args)
        {
            Student stu = new Student();
            /*stu[0] = "XiaoMing";
            Console.WriteLine(stu[0]);
            Console.ReadKey();*/

            while (true)
            {
                string num = Console.ReadLine();
                Console.WriteLine(stu[num]);
            }

        }
    }
    class Student
    {
        private string[] name = new string[10];
        public string this[int index]
        {
            get { return name[index]; }
            set { name[index] = value; }

        }
        private string[] num = { "01", "02", "03" };
        public string this[string index]
        {
            get
            {
                switch (index)
                {
                    case "01":
                        return "XiaoMing";
                    case "02":
                        return "XiaoHong";
                    case "03":
                        return "XiaoHua";
                    default:
                        return "Not Exists";
                }
            }

        }
    }
}

27、命名空间

命名空间是为了解决相同作用域下的命名问题。
在C、C++、C#等语言中,都有命名空间的概念,这是为了防止不同人编写类库发生命名冲突而设计的,命名空间可以使变量、函数名称、类名称作用在本空间内,而其他空间可以使用同样的名称。就好比不同的文件夹下可以有相同的文件名一样,但在相同的文件夹下不能有重复的文件名,命名空间就好比这个虚拟的文件夹。
using关键字使用
命名空间指令:
using关键字表明程序使用的是给定命名空间中的名称。例如,我们在程序中使用System命名空间,其中定义了类Console。我们可以只写: Console.WriteLine ("Hello World");我们可以写完全限定名称: System.Console.WriteLine("Hello World");

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace demo10
{
    class Program
    {
        static void Main(string[] args)
        {
            Class0ne.Student stul = new Class0ne.Student();
            ClassTwo.Student stu2 = new ClassTwo.Student();

        }
    }
}
namespace Class0ne {
    class Student
    {
        public string Name { get; set; }
    }
}
namespace ClassTwo
{
    class Student
    {
        public string Name { get; set; }
    }
}

或者

别名指令:
using别名指令允许起一个别名给命名空间或命名空间中的一个类型。

嵌套命名空间

命名空间可以被嵌套,即可以在一个命名空间内定义另一个命名空间。

namespace Class0ne
{
    namespace RowOne
    {
        class Student
        {
            public string Name { get; set; }
        }
    }
    namespace RowTwo
    {
        class Student
        {
            public string Name { get; set; }
        }
    }
}

28、接口

接口是指定一组函数成员,而不实现他们的引用类型。

接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同“是什么"部分,派生类定义了语法合同“怎么做"部分。

接口使用interface关键字声明,它与类的声明类似。接口声明默认是public的。下面是一个接口声明的实例:
interface IMyInterface;

{

​ void Fun();

}

以上代码定义了接口IMyInterface。通常接口命令以I字母开头,这个接口只有一个方法Fun(,没有参数和返回值。

接口注意的几点:
接口中的方法不能用public abstract等修饰。
接口中只能声明方法,属性,事件,索引器。接口内不能有字段变量,构造函数。
实现接口时,必须和接口的格式致。
必须实现接口的所有方法。

抽象类和接口的区别:

1.抽象类中可以有实现成员(非抽象方法),而接口中的方法只有声明没有实现;
2、抽象类中可以有字段,接口中不能有字段,但可以有属性:
3、抽象类的成员可以使用公有或其他修饰符,接口中成员是隐式公有的,不需要修饰:
4、抽象类是概念的抽象,接口注重行为,抽象类不支持多重继承,而一个类可以实现多个接口。

29、静态和非静态

静态类和非静态类在C#中定义基本是-样的,只是静态定义需要加上static修饰符而已。
静态类与非静态类的区别:
1、静态类只能包含静态成员,否则会抛出编译错误;然而非静态类既可以包含非静态成员也可以包含静态成员。
2、静态类是不能实例化的,之所以不能实例化,是因为静态类会导致C#编译器将该类同时标记为abstract和sealed,并且编译器不会在类型中生成一一个实例的构造函数,从而导致静态类不能实例化,具体原因可以见下图;非静态类可以,并且静态成员的访问只能通过类来进行访问,因为静态成员是属于类的。
静态字段、属性和实例字段、属性的区别:
1.静态成员包括静态字段和静态字段,静态字段-般实现为private,静态属性一般实现为public,从而来体现类 的封装性。
2、静态成员和类相关联,不依赖于对象而存在,只能由类来访问:实例成员与具体类相关联,只能由对象实例访问。
3.静态成员不管创建多少实例对象,都在内存中只有份,实例成员每创建一个实例对象, 都会在内存中分配一块内存区域。
静态方法与实例方法的区别:
1、静态方法只能访问静态成员和方法,但是可以间接通过创建实例对象来访问实例字段、属性和方法;实例方法既可以访问实例成员也可以访问静态成员。
2、静态方法由类访问,实例方法由对象访问。
3、静态方法不能引用this关键字,而实例方法可以。
4、静态方法不能被标识为virtual. abstract或override,静态方法可以被派生类访问, 但是不能被派生类重写。

5、Main方法为静态的,所以Main方法不能直接访问类中的实例字段、属性和方法,否则编译器会报错。
6、静态方法一般用于作为通用的工具类来实现。

注意;当涉及到通用属性时,可以用静态方法统一设置,只需设置一次。

30、值类型和引用类型

值类型:值类型变量存储的是变量的值。(String类型与值类型相同)

引用类型:引用类型变量存储的是变量所在的内存地址,变量本身是一个指向数据的地址。

引用类型和值类型都继承自System.0bject类。不同的是,几乎所有的引用类型都直接从System.0bject继承,而值类型则继承其子类,即直接继承System.ValueType.即System.Value Type本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

31、string和StringBuilder

String的缺点是每次字符串变量的内容发生了改变时,都必须重新分配内存。
StringBuilder通过分配一个缓存,就是一个工作区来解决这些问题,在工作区中队字符串应用StringBuilder类的相关方法。

//5个修改StringBuilder的内容的方法

StringBuilder.Append //将信息追加到当前StringBuilder的结尾。
StringBuilder.AppendFormat //用带格式文本替换字符串中传递的格式说明符。
StringBuilder.Insert//将字符串或对象插入到当前StringBuilder对象的指定索引处。
StringBuilder.Remove //从当前StringBuilder对象中移除指定数量的字符。
StringBuilder.Replace//替换指定索引处的指定字符。

注意:StringBuilder对地址进行操作,始终指向一个地址,大拼接量时使用StringBuilder,可减少内存损耗。

32、re和out的应用与区别

ref:通过引用来传递参数。ref是通过给方法传递值类型的参数,直接操作同个变量的关键字。


原来输出10,加ref后输出20

out:作为个参数修饰符,允许通过引用而不是通过值将参数传递给方法。

ref修饰的参数必须要有值,但是out可以使用一个未赋值的变量作为参数传递。

小结:
Ref:有进有出,参数必须要进行初始化
Out:只出不进,参数不需要进行初始化(一般都是带有其它参数时)

两者也可搭配使用。

33、 is和as的应用

is关键字是判断类型,用于检查对象是否与给定类型兼容,并不进行实际的转换。不成功则不会抛出异常,如果兼容则返回true如果不兼容则返回false。在进行类型转换之前用。

可做判断使用,节约内存。

as运算符用于在两个应用类型之间进行转换,如果转换失败则返回null,并不抛出异常,因此转换是否成功可以通过结果是否为null进行判断,并且只有在运行时才能判断。AS运算符有一定的适用范围,他只适用于引用类型或可以为null的类型。


和强转对比

1.无论是AS和IS运算符,都比直接使用()运算符强制转换更安全。
2、不会抛出异常,免除使用try...catch进行异常捕获的必要和系统开销,只需要判断是否为null.
3、使用AS比使用IS性能更好。

小结
is:由下向上兼容,由上向下不兼容。如果-个对象是某个类型或是其父类型,则返回True
as:转换失败的话,返回的值是null,只要通过是否为空的判断即可进行下面的操作

可以免除trycatch节约资源。

34、隐式类型和初始化器

隐式类型:在隐式类型出现之前,我们在声明一一个变量的时候,总是要为一一个变量指定他的类型。
使用var定义变量时有以下四个特点:
1.必须在定义时初始化。也就是必须是vars= "abcd" 形式,而不能是如下形式: vars;s= "abcd" ;
2.一但初始化完成,就不能再给变量赋与初始化值类型不同的值了。

3.var要求是局部变量。
4.使用var定义变量和object不同,它在效率上和使用强类型方式定义变量完全一样。

注意事项:你不能用var关键字声明一个变量而不给它赋值,因为编译器无法推导出你这个变量是什么类型的。

也可放在循环里

对象初始化器:
1、不具备强制性
2、只能完成属性的初始化

对比使用构造函数:构造函数具有强迫性,必须对构造函数中的参数进行传递,初始化器不具备强制性

小结:
隐式类型:定义的时候必须要进行初始化。
初始化器:不强制初始化其中的属性。要注意,属性间以逗号间隔。只能对属性进行初始化

原文地址:https://www.cnblogs.com/zhuchengbo/p/12622407.html