一些补充
在正式进入面向对象前,先把之前没讲完的东西讲掉。
纯文本字符串
在字符串前加上“@”,就可以让字符串中的转义失效,变成纯文本字符串。
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
string a = "C:\\Files"; // 双反斜杠转义为单反线杠
string b = @"C:\\Files"; // 不转义,就是双反斜杠
Console.WriteLine(a);
Console.WriteLine(b);
}
}
}
输出如下:
C:\Files
C:\\Files
格式化输出
先看例子:
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
int a = 13;
Console.WriteLine("{0} + {0} = {1}", a, a*2);
Console.WriteLine("学生:{0}\n班级:{1}\n座号:{2}", "Lihua", "907", "5");
}
}
}
输出结果如下:
13 + 13 = 26
学生:Lihua
班级:907
座号:5
可以看出,字符串后面的多余数据用逗号隔开,从第一个到最后一个被编上下标0、1、2...只要在字符串中使用{下标}就能调用后面的数据。
数据可以是常量、变量、字面量、表达式,其中,表达式会被计算出结果并输出(如表达式a*2的输出结果为26)。
那么,这有什么用呢?
正常来讲,我们想格式化输出学生信息,可以写成下面代码:
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
string[] names = new string[] {"Lihua", "Ladder", "Step"};
string[] classes = new string[] {"908", "907", "1007"};
string[] ids = new string[] {"1", "15", "5"};
for (int i = 0; i < 3; i++)
{
Console.WriteLine("姓名:"+names[i]+"\n"+"班级:"+classes[i]+"\n"+"座号:"+ids[i]);
}
}
}
}
但是,输出的那一行过于拥挤,且不符合我们的一般阅读习惯,我们用格式化输出就可以很好的改善这个问题:
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
string[] names = new string[] {"Lihua", "Ladder", "Step"};
string[] classes = new string[] {"908", "907", "1007"};
string[] ids = new string[] {"1", "15", "5"};
for (int i = 0; i < 3; i++)
{
Console.WriteLine("姓名:{0}\n班级:{1}\n座号:{2}", names[i], classes[i], ids[i]);
}
}
}
}
怎么样,是不是看着直观了许多?
变量自增
前面说增量表达式的时候有提到,让变量a自增1实际上有三种形式
int a = 0;
a = a + 1 // 完全重新赋值
a += 1 // 上面那种的简略写法
a++ // 增量表达式
实际上三种写法意思相同,但有些地方不一样。
我们在让变量自增的时候,除了自增1,最好是使用第二种写法,和第一种写法效果相同,但能更直观看出意思为变量自增,且灵活性比增量表达式强。
自减就是-=,自乘就是*=,自除以就是/=,以此类推。
将函数作为参数
委托的另一个作用是将函数作为参数传递。
你可以定义一个委托类型参数,然后将对应此委托类型的函数作为委托类型对象的值传入,来达到将函数作为参数的目的,如下面代码:
using System;
namespace Csharp
{
class Program
{
static void PrintLine(string[] n) // 换行输出字符串数组内容
{
foreach(string i in n)
{
Console.WriteLine(i);
}
}
static void Print(string[] n) // 单行(不换行)输出字符串数组内容
{
foreach(string i in n)
{
Console.Write(i);
}
Console.WriteLine();
}
delegate void PointDelegate(string[] n); // 委托(参数对应上面两个函数)
static void PrintByF(string[] n, PointDelegate func) // 可选择对应函数输出的函数
{
func(n); // 使用委托中传递的函数来输出字符串数组
}
static void Main(string[] args)
{
string[] a = new string[] {"Ladder", "Step"};
PrintByF(a, Print); // 不换行输出
PrintByF(a, PrintLine); // 换行输出
}
}
}
运行结果如下:
LadderStep
Ladder
Step
通过将函数作为参数传递,我们即使在两个函数参数相同时不能使用函数重载,也可以通过委托对象不同,达到一套代码执行不同函数的效果。
异常处理
我们在运行代码时经常会报错,而报错后程序就会中断,我们就没有办法继续执行下面的代码。那么,有没有什么方法,能让我们在代码报错前就捕捉住报错,从而继续运行呢?
看下面代码:
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
Console.Write("请输入年龄:");
string userInput = Console.ReadLine();
int userInputNumber = Convert.ToInt32(userInput);
Console.WriteLine("您18年后为{0}岁", userInputNumber + 18);
}
}
}
这是一个简单的程序,用户输入年龄,程序输出用户18年后的年龄。
在这个程序中,我们用到了Convert.ToInt32()函数,这个函数我们在《C#学习笔记1-类型转换》中有学习过,作用是将数字内容的string(如"19823")转为对应的数字(即int类型19823)。
那么,在string不为数字内容时(如"我是字符串"),进行转换,会发生什么?
我们在上面的程序中,将年龄输入为"LadderStep",果然出现报错:

报错信息告诉我们,字符串"LadderStep"不是正确的格式,报错类型为System.FormatException(格式错误)。
我们希望当输入格式错误(即输入非数字)时,让用户重新输入,应该怎么做呢?这时候就可以用到异常处理了:
try
{
可能发生异常的代码块...
}
catch (可能发生的异常类型1 变量名)
{
发生对应异常后执行的代码块...
}
catch (可能发生的异常类型2 变量名)
{
发生对应异常后执行的代码块...
}
finally
{
无论是否有异常都会执行的代码块...
}
有几点需要注意一下:
1.可能发生异常的代码块被try捕捉后一般不会让程序直接报错结束运行,但少数崩溃性错误会,不过即使崩溃,finally里的代码也会被执行,所以崩溃后的处理可以写在finally里,而不是异常处理外。
2.不能只写try,try后面必须跟上catch或finally,至少一个。
3.catch后面也可以不写整个括号,代表捕获一切异常,但不推荐这么做。
4.变量名指的是异常发生后存储异常信息的变量,可以调用此变量名了解异常信息,本质是生成了一个异常类型的对象赋值给变量。
来看修改过的代码:
using System;
namespace Csharp
{
class Program
{
static void Main(string[] args)
{
while (true)
{
Console.Write("请输入年龄:");
string userInput = Console.ReadLine();
try
{
int userInputNumber = Convert.ToInt32(userInput);
Console.WriteLine("您18年后为{0}岁", userInputNumber + 18);
break;
}
catch (FormatException e)
{
Console.WriteLine("输入格式错误,请重新输入");
continue;
}
}
}
}
}
这样,我们就能捕获程序中因意外可能导致的许多异常,让我们的程序更为完备。
下一篇~面向对象!

Comments NOTHING