参考资料:
- C#入门经典(第7版)
1. 变量和表达式
1.1 变量
C#的声明变量的语法:
<type> <name>;
使用变量前需要先声明,再赋值。
例如:
int a = 1;
Console.WriteLine($"a = {a}");
1.2 简单数据类型
整数类型
整型数据示例:
int intVal = 100; // 无后缀
long longVal = 100L; // 可以有或无后缀
uint uintVal = 100U; // 可以有或无后缀
ulong ulongVal = 100UL; // 可以有或无后缀
浮点类型
浮点数据示例
float floatVal = 1.5F; // 有后缀 F
double doubleVal = 1.5; // 可以有或无后缀
decimal decimalVal = 1.5M; // 有后缀 M
其他类型
其他类型示例:
char charval = 'a';
bool boolVal = true;
string stringval = "abc";
1.3 变量命名
基本的命名规则:
- 变量名的第一个字符必须是字符、下划线(_)或@
- 其后的字符可以是字母、下划线或数字
1.4 字符串字面值的转义序列表
1.5 表达式
1.5.1 数学运算符
二元运算符 + 对于字符串类型变量也有意义,对字符串进行拼接。
一元运算符自增、自减的使用,放在操作数前或后。
int a = 1;
a++; // 自增
a--; // 自减
1.5.2 赋值运算符
例如:
int a = 1;
int b = 0;
b += a; // 等价于 b = b + a
1.5.3 符号的优先级
括号可以改变优先级
1.6 命名空间
参考:https://www.runoob.com/csharp/csharp-namespace.html
2. 流程控制
2.1 布尔比较运算符(关系运算符)
int intval = 1;
string stringval = "hello";
bool mybool = false;
bool boolVal = intval < 10; // true
bool boolVal1 = stringval == "world"; // false
bool boolVal2 = mybool != true; // true
2.2 条件布尔运算符
运算符:! ,逻辑非运算符,用来改变逻辑状态,可以使条件为真的变为假,条件为假的变为真。
bool b1 = true;
bool b2 = false;
bool b3 = !(b1 && b2); // true
bool b4 = !(b1 || b2); // false
2.3 分支
- 三元运算符
- if语句
- switch语句
2.3.1 三元运算符
语法:
<test> ? <resultIfTrue> : <resultIfFalse>
根据< test>得到的布尔值,确定运算符的结果是< resultIfTrue>还是< resultIfFalse>。
int a = 10;
string str = a > 10 ? "yes" : "no"; // no
2.3.2 If语句
// If语句
if (<test>) // <test> 计算结果为bool
{
// other code
}
// If-else语句
if (<test>)
{
// other code
}
else
{
// other code
}
If语句是可以嵌套使用的。
2.3.2 switch语句
switch语句的基本结构,< testVar>和< cimparisonVal>进行匹配,如果有匹配上的,执行case中的代码,如果没有,执行default中的代码,break用于跳出switch语句。
switch (<testVar>)
{
case <comparisonVal1>:
// other code
break;
case <comparisonVal2>:
// other code
break;
...
case <comparisonValN>:
// other code
break;
default:
// other code
break;
}
例如:
int intval = 1;
switch (intval)
{
case 0:
Console.WriteLine(1);
break;
case 1:
Console.WriteLine(2);
break;
default:
Console.WriteLine(3);
break;
}
可以将多个case堆放在一起:
int intval = 1;
switch (intval)
{
case 0:
case 1:
case 2:
Console.WriteLine("012");
break;
default:
Console.WriteLine("default");
break;
}
2.4 循环
2.4.1 do-while循环
do-while循环的结构:
do
{
// other code
} while(<Test>);
根据< test> 得到的布尔值,判断是否继续进行循环,为true,继续执行循环,为false,退出循环。do-while循环是先执行循环代码,在进行布尔判断。
例子:
int i = 1;
do
{
Console.WriteLine("{0}", i++);
} while(i <= 10);
2.4.2 while循环
while循环的基本结构:
while (<test>)
{
// other code
}
while循环中的布尔判断会在循环执行前进行,如果< test>为true,执行循环体,如果为false,不执行循环体或跳出循环体。
例如:
int i = 1;
while (i <= 10)
{
Console.WriteLine($"{i++}");
}
2.4.3 for循环
for 循环的基本结构:
for (<initalization>; <condition>; <operation>)
{
// other code
}
for循环可以执行指定的次数,并维护它自己的计数器,定义for循环,需要的信息:
- 初始化计数器变量的起始值
- 继续执行循环的条件,应该涉及计数器
- 每次循环后,对计数器进行一个操作
例子:
int i;
for (i = 1; i <= 10; i++)
{
Console.WriteLine($"{i}");
}
2.4.4 循环中断的方式
- break方式,会立即终止循环
- continue方式,会终止当前循环(继续执行下一次循环)
- return方式,跳出循环以及包含该循环的函数
例如:
for (int i = 1; i <= 10; i++)
{
if ((i % 2) == 0)
{
break;
// continue;
}
Console.WriteLine(i);
}
3. 枚举、结构和数组
3.1 枚举
定义枚举:
enum <typeName>
{
<value1>,<value2>,...,<valueN>
}
声明枚举类型的变量
<typeName> <varName>
为枚举变量赋值
<varName> = <typeName>.<value>
例子:
enum Color
{
Red, Blue, Green, Yellow
}
Color myColor;
myColor = Color.Red;
Console.WriteLine(myColor); // Red
Console.WriteLine((int)myColor); // 0
枚举类型可取的值都存储着一个基本类型的值,默认为int类型,也可以声明其他的基本类型byte,sbyte,short,
ushort,int,uint,long和ulong。默认情况下,每个值都会根据定义顺序开始(从0开始),也可以重写默认值。
修改类型和默认值的语法如下:
enum <typeName> : <underlyingType>
{
<value1> = <actualVal1>,
<value2> = <actualVal2>,
...
<valueN> = <actualValN>
}
例子:
enum orientation: byte
{
north = 1, south = 2, east = 3, west = 4
}
orientation myDirection = orientation.north;
Console.WriteLine($"{myDirection}"); // 等价于 myDirection.ToString() north
Console.WriteLIne($"{(byte)myDirection}"); // 1
3.2 结构
结构是由多个数据组成的数据结构,这些数据可能是不同的数据类型。
定义结构:
struct <typeName>
{
// 声明变量,结构的数据成员
<accesibility> <type> <name>;
}
< accessibility> 使用关键字public,例如:
struct point
{
public int x;
public int y;
}
// 定义结构类型的变量
point myPoint;
// 赋值
myPoint.x = 1;
myPoint.y = 1;
3.3 数组
数组中存储的是同一数据类型的值,通过索引访问数组中的元素。
声明数组:
<type>[] <name>;
// 例如
int[] arr;
初始化数组:
- 使用字面值指定数组的内容
int[] intArray = {1,2,3,4,5};
- 指定数组大小,使用new实例化数组
int[] intArray = new int[5];
- 还可以使用上述的组合方式
int intArray = new int[5]{1,2,3,4,5};
// or
const int arraySize = 5;
int intArray = new int[arraySize ]{1,2,3,4,5};
遍历数组的方式
- foreach方式
foreach循环是对数组进行只读访问,不能改变元素值。
例如:
int[] arr = {1,2,3,4,5};
for (int item in arr)
{
Console.WriteLine(item);
}
- for循环
例如:
int[] arr = {1,2,3,4,5};
for (int i =0; i < arr.Length(); i++)
{
Console.WriteLine(arr[i]);
}
多维数组(矩形数组)
double[,] hillHeitht = {
{ 1.1, 1.2},
{ 2.1, 2.1}
};
// foreach 遍历数组
foreach (double i in hillHeitht)
{
Console.WriteLine(i);
}
int[,] ints = new int[2, 3];
ints[1, 2] = 1;
锯齿数组
锯齿数组的每一行的元素个数可能不一样
int[][] arr1 = new int[2][];
arr1[0] = new int[2];
arr1[1] = new int[3];
int[][] arr2 = new int[3][] {
new int[] {1,3,4},
new int[] {1 },
new int[] {1,2}
};
// 遍历锯齿数组
foreach (int[] temp in arr2)
{
foreach (int item in temp)
{
Console.WriteLine(item);
}
}
4. 字符串相关操作
字符串可以看作是char类型的只读数组,可以通过索引访问字符串中的字符。
string str = "hello world";
char c = str[1]; // 'e'
将字符串转成字符数组
string str = "hello world";
char[] chars = str.ToCharArray(); // 'h','e',..'d'
获取字符串的字符个数
string str = "hello world";
int length = str.Length(); // 11
将字符串中的字母转大写或小写
string str = "Hello World";
// 字母转大写
string strUpper = str.ToUpper(); // HELLO WORLD
// 字母转小写
string strLower = str.ToLower(); // hello world
去掉字符串两端的空格
string str = " hello world ";
string strTrim = str.Trim(); // hello world
// Trim可以删除字符串两端的字符以及空格
string strTrim1 = str.Trim('h','d'); // ello worl
在字符串两端添加字符
string str = "hello world";
string strLeftTrim = str.PadLeft(12); // 默认在左边添加空格,12表示添加后字符串的长度
string strLeftChar = str.PadLeft(12,'-'); // 可以添加其他的字符
// 同理 PadRight 是在字符串的右边添加字符
拆分字符串为字符串数组
string str = "hello world";
string[] strings = str.Split(' '); // ["hello", "world"]
获取字符串的字符串
string str = "hello world";
string substring = str.Substring(1,3); // ell
获取某个字符在字符串中的第一次出现的索引位置
string str = "hello world";
int indexL = str.IndexOf('l'); // 2
int lasIndexL = str.LastIndexOf('l'); // 9
替换字符串中的某些字符串
string str = "hello world";
string newStr = str.Replace("e","o"); // hollo world
5. 函数
// 一个函数示例,有参数列表,函数名,返回值类型
static double Mulitply(double myVal1, double myVal2)
{
return myVal1 * myVal2;
}
// 等价于下面使用 => 编写
static double Multiply(double myVal1, double myVal2) => myVal1 * myVal2;
// 调用函数
Multiply(1.1, 1.2);
在调用函数时,提供的参数必须和函数定义中指定的参数完全匹配,参数的类型,个数和顺序都要匹配。
C#中,函数在定义中的最后一个参数为数组,并且使用params关键字修饰,允许不必传递数组,而传递几个同类型的参数。如下所示
static void Show(string str, params int[] ints)
{
Console.WriteLine($"{str}: ");
foreach( int item in ints )
{
Console.WriteLine($"item: {item}");
}
}
//函数调用
Show("Numbers", 1,2,3,4,5);
5.1 引用参数和值参数
值参数,函数对于传递过来的参数做的任何修改,都不影响参与函数调用时的变量的值。
static void SHowDouble(int val)
{
val *= 2;
Console.WriteLine($"val double = {0}", val);
}
int myNumber = 5;
Console.WriteLine($"myNumer = {myNumber}"); // 5
ShowDouble(myNumber); // 10
Console.WriteLine($"myNumber = {myNumber}"); // 5
使用 ref 关键字指定参数,函数处理的变量与函数调用中使用的变量相同,对于变量的修改都会影响作为参数的变量值。
static void ShowDouble(ref int val)
{
val *= 2;
Console.WriteLine($"val double = {val}");
}
// 函数调用
int myNumber = 5;
Console.WriteLine($"myNumber = {myNumber}"); // 5
ShowDouble(ref myNumber); // 10
Console.WriteLine($"myNumber = {myNumber}"); // 10
作为ref参数的变量的两个限制,1)函数可能引起引用参数的变化,所以不能是常量(const修饰的变量)。2)必须是初始化过的变量
5.2 输出参数
使用 out 关键字,在函数定义和函数调用中用作参数的修饰符,和 ref 关键字的使用相同。
ref 和 out 的区别:
- 未赋值的变量用作ref参数是非法,但是可以用作out参数
- 在函数使用out参数时,必须把它看成尚未赋值
例如:
static int MaxValue(int[] intArray, out int maxIndex)
{
int maxVal = intArray[0];
maxIndex = 0; // 不能缺少
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal )
{
maxVal = intArray[i];
maxIndex = i;
}
}
return maxVal;
}
// 调用函数
int[] myArray = {1,8,3,6,2,5,9,3,0,2};
int maxIndex;
Console.WriteLine($"{MaxValue(myArray, out maxIndex)}"); // 9
Console.WriteLine($"{maxIndex}"); // 6
5.3 结构函数
结构函数是在结构中的函数
例如:
struct CustomerName
{
public string firstName;
public string lastName;
public string Name() => firstName + " " + lastName;
}
// 使用结构函数
CustomerName myCustromer;
myCustromer.firstName = "John";
myCustromer.lastName = "Franklin";
Console.WriteLine(myCustromer.Name()); // John Franklin
5.4 函数的重载
函数重载允许创建多个同名函数,但是需要有不同的参数列表。函数的签名包含函数名称和其参数列表。
例如:
static double MaxValue(double[] doubleArray)
{
//...
}
static int MaxValue(int[] intArray)
{
//...
}
static void ShowDouble(ref int val)
{
// ...
}
static void ShowDouble(int val)
{
// ...
}
5.5 委托
委托(delegate)是一种能够存储函数引用的类型。委托的声明类似函数,但不带函数体,且需要 delegate 关键字修饰,委托的声明指定了一个返回类型和一个参数列表。委托可以作为参数传递给函数。
例如:
// 定义委托
delegate double ProccessDelegate(double param1, double param2);
// 一些函数
static double Multiply(double param1, double param2) => param1 * param2;
static double Divide(double param1, double param2) => param1 / param2;
// 声明委托
ProcessDelegate process;
// 初始化委托
process = new ProcessDelegate(Multiply);
// or
process = Divide;
// 使用委托,调用所选函数
double param1 = 1.1;
double param2 = 2.2;
double result = process(param1, param2);
6.异常处理
C#用于异常处理的3个关键字,try、catch、finally,必须在连续的代码中使用。
try…catch…finally的基本结构:
try
{
// ...
}
catch (exceptionType e) when (filterIsTrue)
{
// ...
}
finally
{
//...
}
try 代码块中包含可能存在的异常代码。
catch代码块中包含抛出异常时需要执行的代码,excpeitonType设置为响应特定类型的异常类型,可以提供多个catch块,还可以通过when关键字进行异常过滤。
finally代码块,包含始终执行的代码。
在try块的代码出现异常后,依次发生的事件如下:
throw关键字,用于抛出一个异常。
throw new System.Exception();
其他
一些API的收集:
- Console.WriteLine() 将字符串输出到屏幕
- Console.ReadLine() 接受输入的字符串
- Convert.ToDouble() 将字符串数值转成Double类型
- Convert.ToInt32() 将字符串数值转成Int类型
- typeOf() 获取类型的System.Type对象,参考:https://www.cnblogs.com/youmingkuang/p/14271118.html
仅供个人参考学习