C# 入门教程

2023-11-09

C#简介

C#是一个简单的,现代的,通用的,面向对象的编程语言,它是由微软(Microsoft)开发的。
下面列出了C#成为一种广泛应用的专业语言的原因:

  • 现代的、通用的编程语言。
  • 面向对象。
  • 面向组件。
  • 容易学习。
  • 结构化语言。
  • 它产生高效率的程序。
  • 它可以在多种计算机平台上编译。
  • .Net框架的一部分。

C# 强大的编程功能

虽然C#的构想十分接近于传统的高级语言C和C++,是一门面向对象的编程语言,但是它与JAVA非常相似,有很大强大的编程功能,因此得到广大程序员的青睐。
下面列出C#的一些重要功能:

  • 布尔条件(Boolean Conditon)
  • 自动垃圾回收(Automatic Garbage Collection)
  • 标准库(Standard Library)
  • 组件版本(Assembly Versioning)
  • 属性(Properties)和事件(Events)
  • 委托(Delegates)和事件管理(Events Management)
  • 易于使用的泛型(Generics)
  • 索引器(Indexers)
  • 条件编译(Conditional Compilation)
  • 简单的多线程(Multithreading)
  • LINQ和Lambda表达式
  • 集成Windows

C#的集成开发环境(Integrated Development Environment - IDE)

微软(Microsoft)提供了下列用于C#编程的工具:

  • Visual Studio 2010(VS)
  • Visual C# 2010 Express(VCE)
  • Visual Web Developer
    后面两个是免费使用的,可以从微软官网下载。Visual C# 2010 Express 和 Visual Web Developer版本是Visual Studio的定制版本, 具有相同的外观和感官。他们保留了Visual Studio的大部分功能。您可以从 Microsoft Visual Studio上进行下载。

在Linux 或 Mac OS上编写C#程序

虽然.NET 框架是运行在Windows操心系统上,但是也有一些运行与其他操作系统上的版本可选择。Mono 是.NET框架的一个开源版本,它包含了一个C#编译器, 且可运行于多种操作系统上,比如各种版本的Linux和Mac OS。如需了解更多,可以访问Go Mono
Mono的目的不仅仅是跨平台的运行微软的.NET应用程序,而且也为Linux开发者提供了更好的开发工具。Mono 可运行在多种操作系统上, 包括Android 、BSD 、iOS、Linux、 OS X、 Windows、 Solaris 和UNIX。

C#程序结构

C# Hello World 实例

一个C#程序主要包含以下部分:

  • 命名空间(Namespace declaration)
  • 一个class
  • Class方法
  • Class属性
  • 一个Main方法
  • 语句(Statement)& 表达式(Expressions)
  • 注释

C#文件的后缀为**.cs**

以下创建了一个test.cs文件, 文件包含了可以打印"hello world"的简单代码:

using System;
namespace HelloWorldApplication
{
    class HelloWorld
    {
        static void Main(sting[] args)
        {
            /*我的第一个C#程序*/
            Console.WriteLine("hello world");
            Console.ReadKey();
        }
    }
}

当上面的代码被 编译并执行后,结果如下:

hello world;

我们来看一下上面程序的各个部分:

  • 程序的第一行using System; using关键字用于在程序中包含System的命名空间。一个程序可以有多个using,即包含多个命令空间(和从语言中的#include< stido.h> 用处相似)
  • 下一行是namespace声明。一个namespace里面包含了一系列的类。HelloWorldApplication命名空间包含了类HelloWorld。
  • 下一行是class声明。 类HelloWorld包含了程序使用的数据和方法声明。类一般包含多个方法,方法定义了类的行为。在这里HelloWorld类只有一个方法Main。
  • 下一行定义了Main方法,是所有C#程序的入口点。Main方法说明当执行时,类将做什么动作。
  • 下一行//是注释,将会被编译器忽略。
  • Main方法通过语句**Console.WriteLine(“hello world”); 指定了它的行为。
    WriteLine是一个定义在System命名空间中的Console类的一个方法。该语句会在屏
    幕上显示信息“hello World”。
  • 最后一行Console.ReadKey(); 是针对VS.NET用户的。这使得程序会等待一个按键
    的动作,防止程序从Visual Studio .NET启动时屏幕会快速运行并关闭。

以下几点需要注意:

  • C#大小写敏感
  • 所有语句和表达式必须以分号(;)结尾
  • 程序从Main方法开始执行
  • 与Java不同的是,文件名可以不同于类的名称

编译 & 执行 C#程序

如果您使用Visual Studio .NET编译和执行C#程序,请按照下面的步骤操作:

  • 启动Visual Studio
  • 在菜单栏上, 选择File -> New -> Project
  • 从模板中选择Visual C#,然后选择Windows
  • 选择Console Application
  • 为您的项目制定一个名称,然后点击OK按钮
  • 新项目会出现在解决方案资源管理器(Solution Explorer)中。
  • 在代码编辑器(Code Editor)中编写代码
  • 点击Run按钮或者按下F5健来运行程序。会出现一个命令提示符窗口(Command Promotion Windows), 显示 hello World

您也可以使用命令行代替Visual Studio IDE来编译C#程序:

  • 打开一个文本编辑器,添加上面的代码
  • 保存文件为HelloWorld.cs
  • 打开命令提示符工具,定位到文件所保存的目录
  • 键入csc helloworld.cs 并按下enter健来编译代码
  • 如果代码没有错误,命令行提示符会进入下一行,并生成HelloWorld.ext可执行文件
  • 接下来, 键入helloworld来执行程序
  • 您将看到“hello World”显示在屏幕上

C#基本语法

以Rectangle(矩形)对象为例,它具有length和width属性,根据这些属性可以计算面积。我们以一个Rectangle类的实现来讲解C#的基本语法:

using System;
namespace RectangleApplication
{
    class Rectangle
    {
        //成员变量
        double length;
        double width;
        public void Acceptdetails()
        {
            length = 4;
            width = 3;
        }
        public double GetArea()
        {
            return length * width;
        }
        public void Display()
        {
            Console.WriteLine("length:{0}", length);
            Console.WriteLine("width:{0}", width);
            Console.WriteLine("Area:[0}", GetArea());
        }
    }

    class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            Reatangle r = new Rectangle();
            r.Acceptdetails();
            r.Display();
            Console.ReadLine();
        }
    }
}

当上面的代码被编译执行时,他会产生下列结果:

length: 4
width: 3
Area: 12

using关键字

在任何C#程序中的第一条语句都是:

using System;

class 关键字

class关键字用于声明一个类

C#中的注释

注释是用于解释代码。编译器会忽略注释的条目。在C#程序中,多行注释用/* XXXXX */ ,如下所示:

/*This program demonstrates 
The basic sysntax of C# programming
Language */

单行注释是用"//"符号表示。例如:

}//end class rectangle

成员变量

变量是类的属性或数据成员,用于存储数据。在上面的程序中,Rectangle类有两个成员变量,名为length和width。

成员函数

函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。我们举例的类Rectangle包含了三个成员函数:AcceptDetails、GetArea和Display。

实例化一个类

在上面的程序中,类ExecuteRectangle是一个包含Main() 方法和实例化Rectangle类的类。

标识符

标识符是用来识别类、变量、函数或任何其他用户定义的项目。在C#中,类的命名必须遵守如下基本规则:

  • 标识符必须以字母、下划线或 @ 开头,后面可以跟一系列的字母、数字(0-9)、下划线(_)、@。
  • 标识符第一个字符不能是数字
  • 标识符必须不包含任何嵌入的空格或符号,比如?-+!%……&*()[ ] { } . ; :" ’ / \
  • 标识符不能是C#的关键字。除非它们有一个@前缀。 .例如,@if是有效的标识符,但if不是,因为if是关键字
  • 标识符必须区分大小写。大写字母和小写字母被认为是不同的字母
  • 不能与C#的类库名称相同

C#关键字

关键字是C#编译器预定义的保留字。这些关键字不能用作标识符,但是,如果想使用这些关键字作为标识符,可以在关键字前面加上@字符作为前缀。
在C#中,有些关键字在代码的上下文中有特殊意义。如get和set,这些被称为上下文关键字。下表列出了C#中的保留关键字和上下文关键字:

保留关键字
abstract as base bool break byte case
catch char checked class const continue decimal
default delegate do double else enum event
explict extern false finally fixed float for
foreach goto if implict in in(generic modifier) int
interface internal is lock long namespace new
null object operator out out(generic modifier) override params
private protected public readonly ref return sbyte
sealed short sizeof stackalloc static string struct
switch this throw true try typeof uint
ulong unchecked unsafe ushort using virtual void
volatile while
上下文关键字
add alias ascending descending dynamic from
global group into join let orderby
partial(method) remove select set

C#数据类型

在C#中,变量分为一下几种类型:

  • 值类型(Values type)
  • 引用类型(Reference types)
  • 指针类型(Pointer types)

值类型(Values types)

值类型变量可以直接分配给一个值,它们是从类System.ValueType 中派生的。
值类型直接包含数据。比如int、char、float, 它们分别存储数字,字符、浮点数。当您声明一个int类型时,系统分配内存类存储值。
下表列出了C#2010中可用的值类型:

类型 描述 范围 默认值
bool 布尔值 True或False False
byte 8位无符号整数 0到255 0
char 16位Unicode字符 U +0000到U+ffff ‘\0’
decimal 128位精确的十进制值,28-29有效位数 (-7.9 x 1028)/100 28 0.0M
double 64位双精度浮点型 (+/-)5.0 x 10-324到(+/-)1.7 x 10308 0.0D
float 32位单精度浮点型 -3.4 x 1038 到 +3.4 x 10 38 0.0F
int 32位有符号整数类型 -2,147,483,648到2,147,483,647 0
long 64位有符号整数类型 -9,223,372,0.6,854,775,808到9,223,372,036,854,775,807 0L
sbyte 8位有符号整型 -128到127 0
short 16位有符号整数类型 -32768到32767 0
uint 32位无符号整数类型 0到4,294,967,295 0
ulong 64位无符号整数类型 0到18,446,744,073,709,551,615 0
ushort 16位无符号整数类型 0到65,535 0

如需得到一个类型或一个变量咋特定平台上的准确尺寸,可以使用sizeof方法,表达式sizeof(type)返回以字节为单位的尺寸大小。下面举例获取任何机器上int类型的尺寸:

using System;
namespace DataTypeApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Size of int:{0}", sizeof(int));
            Console.ReadLine();
        }
    }    
}

执行上面的代码,结果如下:

Size of int: 4

引用类型(Reference types)

引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
引用类型指的是一个内存位置,使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的引用类型有:object、dynamic和string

对象(Object)类型

对象类型是C#通用类型系统(Common Type System- CTS)中所有数据类型的终极基类。
Object 是 System.Object类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型和用户自定义类型)的值。但是,在分配之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为装箱;另一个方面,当一个对象类型转换为值类型时,则被称为拆箱

object obj;
obj = 100; //这是装箱

动态(Dynamic)类型

动态数据类型变量中可以存储任何类型的值,这些变量的类型在运行时才会进行检查。
声明动态数据类型的语法:

dynamic <variable_name> = value;

例如:

dyamic d = 20;

动态类型与对象类型相似,但是对象类型变量检查是在编译时发生的,而动态类型变量的检查是在运行时发生的。

字符串(String)类型

字符串(String)类型允许您给变量分配任何字符串值。字符串(String)类型是System.String类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和@引号。
例如:

String str = "hello world";

一个 @ 引号字符串:

@"hello world"

C#string 字符串的前面可以加@(称作“逐字字符串”)将转义字符(\)当作普通字符对待,比如:

sting str = @"C:\Windows";
等价于:
string str = "C:\\Windows";

@字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。

string str = @"<script type =""text/javascript"">
                  <!--
                  -->
                  </script>";

用户自定义的引用类型有:class、interface或delegate。

指针(Pointer types)类型

指针类型变量存储另一种类型的内存地址。C#中的指针与C或C++中的指针有相同的功能。
什么指针类型的语法:

type* identifier

例如:
char* cptr;
int* iptr;

类型转换

类型转换是把数据从一种类型转换为另一种类型。在C#中,类型转换有两种形式:

  • 隐式类型转换:这种转换是C#默认的以安全方式进行的转换,不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
  • 显示类型转换:即强制类型转换。显示转换需要强制转换运算符,而且强制转换会造成数据丢失。

下面的实例展示了一个显示的类型转换:

using System;
namespace ExplicitConversion
{
    static void Main(string[] args)
    {
        double d = 512.6;
        int a;
        //强制转换double为int
        a =  (int)d;
        Console.WriteLine("a = {0}", a);
        Console.ReadKey();        
    }     
}

上方代码被编译并执行后,结果如下:

5673

C#类型转换方法

C#提供了下列内置的类型转换方法:

序号 方法&描述
1 ToBoolean 如果可能的话,把类型转换为布尔类型
2 ToByte 把类型转换为字节类型
3 ToChar 如果可能的话,把类型转换为Unicode字符类型
4 ToDateTime把类型(整数或者字符串类型)转换为日期-时间 结构
5 ToDecimal 把浮点或整数类型转换为十进制类型
6 ToDouble 把类型转换为双进度浮点型
7 ToInt16 把类型转换为16位整数类型
8 ToInt32 把类型转换为32位整数类型
9 ToInt64 把类型转换为64位整数类型
10 ToSbyte 把类型转换为有符号字节类型
11 ToSingle把类型转换为小浮点数类型
12 ToString 把类型转换为字符串类型
13 ToType 把类型转换为指定类型
14 ToUInt16 把类型转换为16位无符号整数类型
15 ToUInt32 把类型转换为32位无符号整数类型
16 ToUInt64 把类型转换为64位无符号整数类型

下面实例把不同值的类型转换为字符串类型:

using System;
namespace TypeConversionApplication
{
    class StringConversion
    {
        static void Main(string[] args)
        {
            int i =  80;
            float f = 51.006f;
            double d = 123.2563;
            bool b = true;
            Console.WriteLine(i.ToString());
            Console.WriteLine(f.ToString());
            Console.WriteLine(d.ToString());
            Console.WriteLine(b.ToString());
        }
    }
}

上面代码编译并执行后,结果如下:

80
51.006
123.2563
True

C# 变量

一个变量只不过是一个工程序操作存储的名字。在C#中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。
C#的基本类型大致可以分为以下几类:

类型 举例
整数类型 sbyte、byte、short、ushort、int、 uint、long、ulong和char
浮点型 float和double
十进制类型 decimal
布尔类型 true或false
空类型 可为空值的数据类型

接受来自用户的值

System命名空间中的Console类提供了一个函数ReadLine(), 用于接收来自用户的输入,并把它存储到一个变量中。
例如:

int num;
num = Convert.ToInt32(Console.ReadLine());

函数Convert.ToInt32()把用户输入的数据转换为int数据类型。因为Console.ReadLine()只接受字符串格式的数据。

C#运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C#的内置运算符分类如下:

  • 算数运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 其他运算符

算术运算符为所以所有事

下表显示了C#支持的所有算术运算符。假设变量A的值为10,变量B的值为20, 则:

运算符 描述 实例
+ 把两个数相加 A + B = 30
- 从第一个操作数中减去第二个操作数 A - B = -10
* 把两个数相乘 A* B = 200
/ 把两个数相除 B / A = 2
% 取模运算符,整除后的余数 B % A = 0
++ 自增运算符,整数值加1 A++ 得到11
自减运算符,整数值将减少1 A–得到9

下面对自增(++)和自减运算符进行详细讲解:

  • c = a++:先将a赋值给c,再对a进行自增运算。
  • c = ++a:先将a进行自增运算,再将a赋值给c。
  • c = a–: 先将a赋值给c,再对a进行自减运算。
  • c = --a:先将a进行自减运算,再将a赋值给c。

通过下面的实例来讲解上方的运算:

using System;
namespace OperatorsApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 1;
            int b;
            //a++ 先赋值再进行自增运算
            b = a++;
            Console.WriteLine("a = {0}", a);
            Console.WriteLine("b = {0}", b);
            Console.ReadLine();

            //++a 先进行自增减运算再赋值
            a = 1//重新进行初始化
            b = ++a;
            Console.WriteLine("a = {0}", a);
            Console.WriteLine("b = {0}", b);
            Console.ReadLine();
            
            //a-- 先进行赋值,再进行自减运算
            a = 1;  //重新进行初始化
            b = a--;
            Console.WriteLine("a = {0}", a);
            Console.WriteLine("b = {0}", b);
            Console.ReadLine();

            //--a 先进行自减运算,再赋值
            a = 1; // 重新进行初始化
            b = --a;
            Console.WriteLine("a = {0}", a);
            Console.WriteLine("b = {0}", b);
            Console.ReadLine();        
            
        }
    }
     
}

执行以上程序,输出结果为:

a = 2
b = 1
a = 2
b = 2
a = 0
b = 1
a = 0
b = 0

关系运算符

下面列出了C#支持的所有运算符。假设变量A为10, 变量的值为20,则:

运算符 描述 实例
== 检查两个操作数是否相等,如果现等则条件为真 (A == B)不为真
!= 检查两个操作数是否相等,如果不相等则条件为真 (A != B)为真
> 检查左操作数是否大于右操作数,如果是则条件为真 (A > B)不为真
< 检查左操作数是否小于右操作数,如果是则条件为真 (A < B)为真
>= 检查左操作数是否大于或等于右操作数,如果是则条件为真 (A >= B) 不为真
<= 检查左操作数是否小于或等于右操作数,如果是则条件为真 (A <= B)为真

逻辑运算符

下表列出了C#支持的所有运算符。假设变量A为布尔值True, 变量B为布尔值false,则:

运算符 描述 实例
&& 称为逻辑与运算符,如果两个操作数都非零,则条件为真 (A && B)为假
|| 称为逻辑或运算符,如果两个操作数中有任意一个非零,则条件为真 (A
! 称为逻辑非运算符,用来逆转操作数的逻辑状态,如果条件为真则逻辑非运算符将使其为假 !(A && B)为真

位运算符

位运算符作用于位,并逐位执行操作。&(位与),|(位或)和^(异或)的真值表如下:

p q p&q p|q p^q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
假设如果A=60,且B = 13, 现在以二进制格式表示,他们如下所示:
A = 0011 1100
B = 0000 1101

A & B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~A = 1100 0011 (每个位取反)
A >> 2 = 15 (即A / 22) A右移两位
A << 2 = 240 (即A * 22) A左移2位

赋值运算符

下表列出了C#支持的赋值运算符:

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 C
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C *= A 相当于 C = C * A
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&= 按位与且赋值运算符 C &= 2 等同于 C = C & 2
^= 按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2
|= 按位或且赋值运算符 C

其他运算符

下表列出了C#支持的其他一些重要的运算符,包括sizeof,typeof和?:。

运算符 描述 实例
sizeof() 返回数据类型的大小 sizeof(int), 将返回4
typeof() 返回class的类型 typeof(StreamReader)
& 返回变量的地址 &a; 将得到变量的实际地址
* 变量的指针 *a; 将指向一个变量。
?: 条件表达式 如果条件为真 ? 则为 X : 否则为 Y
is 判断对象是否为某一类型。 If( Ford is Car) // 检查 Ford 是否是 Car 类的一个对象。
as 强制转换,即使转换失败也不会抛出异常。 Object obj = new StringReader(“Hello”); StringReader r = obj as StringReader;

C# 中的运算符优先级

下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。

类别 运算符 结合性
后缀 () [] -> . ++ – 从左到右
一元 + - ! ~ ++ – (type)* & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 << >> 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR | 从左到右
逻辑与 AND && 从左到右
逻辑或 OR || 从左到右
条件 ?: 从右到左
逗号 , 从左到右

判断

下面是大多数编程语言中典型的判断结构的一般形式:
在这里插入图片描述

判断语句

C#提供了以下类型的判断语句。

if语句

一个if语句 由一个布尔表达式后跟一个或多个语句组成。

if的语法:
```javascript
if (boolean_expression)
{
    /* 如果布尔表达式为真,则执行该语句*/
 }
如果布尔表达式为 true,则 if 语句内的代码块将被执行。如果布尔表达式为 false,则 if 语句结束后的第一组代码(闭括号后)将被执行。
**实例**
```javascript
using System

namespace ConditionChoose
{
 
 class Program
 {
     static void Main(string[] args)
     {
         /*局部变量的定义*/
         int a = 20;
         /*使用if语句检查布尔条件*/
         if (a > 10)
         {
             Console.WriteLine("a 大于 10");
         }
         Console.WriteLine("a 的值是{0}", a);
         Console.ReadLine();
     }
 }
}

当上面的代码被编译和执行时,结果如下:

a 大于 10
a 的值是20

if…else语句

一个if语句后可跟一个可选的else语句, else语句在布尔表达式为假时执行。其语法如下:

if(boolean_expression)
{
    /*如果表达式为真将执行的语句*/
}
else
{
    /*如果表达式为假将执行的语句*/
}

**实例**
```javascript
using System

namespace ConditonChoose
{
    class Program
    {
        static void Main(string[] args)
        {
               int a = 20;
                /*检查布尔条件*/
                if (a > 30)
                {
                        Console.WriteLine("a 大于 30")
                }
                else
                {
                    Console.WriteLine("a  小于 30")
                }
                Console.WriteLine("a 的值是{0}", a);
                Console.ReadLine();
          }
    }
}

当上面的代码被编译和执行时,结果如下:

a  小于 30
a的值是20

if…else if…else 语句

一个 if 语句后可跟一个可选的 else if…else 语句,这可用于测试多种条件。

当使用 if…else if…else 语句时,以下几点需要注意:

  • 一个 if 后可跟零个或一个 else,它必须在任何一个 else if 之后。
  • 一个 if 后可跟零个或多个 else if,它们必须在 else 之前。
  • 一旦某个 else if 匹配成功,其他的 else if 或 else 将不会被测试。

**语法如下:

if(boolean_expression 1)
{
   /* 当布尔表达式 1 为真时执行 */
}
else if( boolean_expression 2)
{
   /* 当布尔表达式 2 为真时执行 */
}
else if( boolean_expression 3)
{
   /* 当布尔表达式 3 为真时执行 */
}
else 
{
   /* 当上面条件都不为真时执行 */
}

实例

using System;

namespace DecisionMaking
{
   
    class Program
    {
        static void Main(string[] args)
        {

            /* 局部变量定义 */
            int a = 100;

            /* 检查布尔条件 */
            if (a == 10)
            {
                /* 如果 if 条件为真,则输出下面的语句 */
                Console.WriteLine("a 的值是 10");
            }
            else if (a == 20)
            {
                /* 如果 else if 条件为真,则输出下面的语句 */
                Console.WriteLine("a 的值是 20");
            }
            else if (a == 30)
            {
                /* 如果 else if 条件为真,则输出下面的语句 */
                Console.WriteLine("a 的值是 30");
            }
            else
            {
                /* 如果上面条件都不为真,则输出下面的语句 */
                Console.WriteLine("没有匹配的值");
            }
            Console.WriteLine("a 的准确值是 {0}", a);
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

没有匹配的值
a 的准确值是 100

嵌套if语句

在 C# 中,嵌套 if-else 语句是合法的,这意味着您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。

语法

if( boolean_expression 1)
{
   /* 当布尔表达式 1 为真时执行 */
   if(boolean_expression 2)
   {
      /* 当布尔表达式 2 为真时执行 */
   }
}

您可以嵌套 else if…else,方式与嵌套 if 语句相似。
实例

using System;

namespace DecisionMaking
{
   
    class Program
    {
        static void Main(string[] args)
        {

            //* 局部变量定义 */
            int a = 100;
            int b = 200;

            /* 检查布尔条件 */
            if (a == 100)
            {
                /* 如果条件为真,则检查下面的条件 */
                if (b == 200)
                {
                    /* 如果条件为真,则输出下面的语句 */
                    Console.WriteLine("a 的值是 100,且 b 的值是 200");
                }
            }
            Console.WriteLine("a 的准确值是 {0}", a);
            Console.WriteLine("b 的准确值是 {0}", b);
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

a 的值是 100,且 b 的值是 200
a 的准确值是 100
b 的准确值是 200

switch 语句

一个 switch 语句允许测试一个变量等于多个值时的情况。每个值称为一个 case,且被测试的变量会对每个 switch case 进行检查。
语法

switch(expression){
    case constant-expression  :
       statement(s);
       break; 
    case constant-expression  :
       statement(s);
       break; 
  
    /* 您可以有任意数量的 case 语句 */
    default : /* 可选的 */
       statement(s);
       break; 
}

switch 语句必须遵循下面的规则:

  • switch 语句中的 expression 必须是一个整型或枚举类型,或者是一个 class 类型,其中 class 有一个单一的转换函数将其转换为整型或枚举类型。
  • 在一个 switch 中可以有任意数量的 case 语句。每个 case 后跟一个要比较的值和一个冒号。
  • case 的 constant-expression 必须与 switch 中的变量具有相同的数据类型,且必须是一个常量。
  • 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到 break 语句为止。
  • 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
  • 不是每一个 case 都需要包含 break。如果 case 语句为空,则可以不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止。
  • C# 不允许从一个 case 部分继续执行到下一个 case 部分。如果 case 语句中有已经执行,则必须包含 break 或其他跳转语句。
  • 一个 switch 语句可以有一个可选的 default 语句,在 switch 的结尾。default 语句用于在上面所有 case 都不为 true 时执行的一个任务。default 也需要包含 break 语句,这是一个良好的习惯。
  • C# 不支持从一个 case 标签显式贯穿到另一个 case 标签。如果要使 C# 支持从一个 case 标签显式贯穿到另一个 case 标签,可以使用 goto 一个 switch-case 或 goto default。

实例

using System;

namespace MyApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      int day = 4;
      switch (day)
      {
        case 1:
          Console.WriteLine("Monday");
          break;
        case 2:
          Console.WriteLine("Tuesday");
          break;
        case 3:
          Console.WriteLine("Wednesday");
          break;
        case 4:
          Console.WriteLine("Thursday");
          break;
        case 5:
          Console.WriteLine("Friday");
          break;
        case 6:
          Console.WriteLine("Saturday");
          break;
        case 7:
          Console.WriteLine("Sunday");
          break;
      }    
    }
  }
}

执行结果根据当天日期有所不同,我这里执行这天的结果为:

Thursday

以下实例判断学生的成绩,包含了 default 语句:

using System;

namespace DecisionMaking
{
   
    class Program
    {
        static void Main(string[] args)
        {
            /* 局部变量定义 */
            char grade = 'B';

            switch (grade)
            {
                case 'A':
                    Console.WriteLine("很棒!");
                    break;
                case 'B':
                case 'C':
                    Console.WriteLine("做得好");
                    break;
                case 'D':
                    Console.WriteLine("您通过了");
                    break;
                case 'F':
                    Console.WriteLine("最好再试一下");
                    break;
                default:
                    Console.WriteLine("无效的成绩");
                    break;
            }
            Console.WriteLine("您的成绩是 {0}", grade);
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

做得好
您的成绩是 B

嵌套switch语句

您可以把一个 switch 作为一个外部 switch 的语句序列的一部分,即可以在一个 switch 语句内使用另一个 switch 语句。即使内部和外部 switch 的 case 常量包含共同的值,也没有矛盾。
语法

switch(ch1)
{
   case 'A':
      printf("这个 A 是外部 switch 的一部分" );
      switch(ch2)
      {
         case 'A':
            printf("这个 A 是内部 switch 的一部分" );
            break;
         case 'B': /* 内部 B case 代码 */
      }
      break;
   case 'B': /* 外部 B case 代码 */
}

实例

using System;

namespace DecisionMaking
{
   
    class Program
    {
        static void Main(string[] args)
        {
            int a = 100;
            int b = 200;

            switch (a)
            {
                case 100:
                    Console.WriteLine("这是外部 switch 的一部分");
                    switch (b)
                    {
                        case 200:
                        Console.WriteLine("这是内部 switch 的一部分");
                        break;
                    }
                    break;
            }
            Console.WriteLine("a 的准确值是 {0}", a);
            Console.WriteLine("b 的准确值是 {0}", b);
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

这是外部 switch 的一部分
这是内部 switch 的一部分
a 的准确值是 100
b 的准确值是 200

? :运算符

我们已经在前面的章节中讲解了 条件运算符 ? :,可以用来替代 if…else 语句。它的一般形式如下:

Exp1 ? Exp2 : Exp3;

其中,Exp1、Exp2 和 Exp3 是表达式。请注意,冒号的使用和位置。
? 表达式的值是由 Exp1 决定的。如果 Exp1 为真,则计算 Exp2 的值,结果即为整个 ? 表达式的值。如果 Exp1 为假,则计算 Exp3 的值,结果即为整个 ? 表达式的值。

C#循环

有的时候,可能需要多次执行同一块代码。一般情况下,语句是顺序执行的:函数中的第一个语句先执行,接着是第二个语句,依此类推。

循环类型

while 循环

只要给定的条件为真,C#中的while循环语句会重复执行一个目标语句
语法

while(condition)
{
   statement(s);
}

在这里,statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块。condition 可以是任意的表达式,当为任意非零值时都为真。当条件为真时执行循环。
当条件为假时,程序流将继续执行紧接着循环的下一条语句。

实例

using System;

namespace Loops
{
   
    class Program
    {
        static void Main(string[] args)
        {
            /* 局部变量定义 */
            int a = 10;

            /* while 循环执行 */
            while (a < 20)
            {
                Console.WriteLine("a 的值: {0}", a);
                a++;
            }
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19

for/foreach 循环

一个 for 循环是一个允许您编写一个执行特定次数的循环的重复控制结构。
语法

for ( init; condition; increment )
{
   statement(s);
}

下面是 for 循环的控制流:

  • init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。

  • 接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。

  • 在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。

  • 条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。

实例

using System;

namespace Loops
{
   
    class Program
    {
        static void Main(string[] args)
        {
            /* for 循环执行 */
            for (int a = 10; a < 20; a = a + 1)
            {
                Console.WriteLine("a 的值: {0}", a);
            }
            Console.ReadLine();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19

C# 也支持foreach循环,使用foreach可以迭代数组或者一个集合对象。

以下实例有三个部分:

  • 通过 foreach 循环输出整型数组中的元素。
  • 通过 for 循环输出整型数组中的元素。
  • foreach 循环设置数组元素的计算器。
class ForEachTest
{
    static void Main(string[] args)
    {
        int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
        foreach (int element in fibarray)
        {
            System.Console.WriteLine(element);
        }
        System.Console.WriteLine();


        // 类似 foreach 循环
        for (int i = 0; i < fibarray.Length; i++)
        {
            System.Console.WriteLine(fibarray[i]);
        }
        System.Console.WriteLine();


        // 设置集合中元素的计算器
        int count = 0;
        foreach (int element in fibarray)
        {
            count += 1;
            System.Console.WriteLine("Element #{0}: {1}", count, element);
        }
        System.Console.WriteLine("Number of elements in the array: {0}", count);
    }
}

输出结果为:

0
1
1
2
3
5
8
13

0
1
1
2
3
5
8
13

Element #1: 0
Element #2: 1
Element #3: 1
Element #4: 2
Element #5: 3
Element #6: 5
Element #7: 8
Element #8: 13
Number of elements in the array: 8
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 入门教程 的相关文章

随机推荐

  • 极简光线追踪入门

    阅读本文不需要任何图形学基础 这里抛砖引玉 希望勾起读者对光线追踪的兴趣 前言 光线追踪原理简单 并且可以抛开图形学的一堆理论 单独提出来讲 本文不需要任何图形学基础 看完本文后 将能够实现以下效果 图1 光线追踪效果 原理 光线追踪算法由
  • linux文件夹大小4096,Linux文件系统之文件、分区大小限制

    各种文件系统的限制 NTFS Windows 支持最大分区2TB 最大文件2TB FAT16 Windows 支持最大分区2GB 最大文件2GB FAT32 Windows 支持最大分区128GB 如果使用磁盘管理进行分区 最大为32GB
  • Docker自定义network搭建kafka

    昨天在搞spring cloud bus 想到用kafka实现消息总线 然后就用docker起了一个zookeeper和kafka 本人docker版本是17 06 采用机器是Ubuntu18版本 详细安装kafka的过程如下 1 dock
  • 反病毒工具-VirtualKD

    KD Kernel Debug 简介 它是一款 虚拟机辅助调试开源工具 版本支持情况 当前2 7版本支持Win8及以前系统 官网 http virtualkd sysprogs org 当你需要高效地调试一台虚拟机你需要它 双机调试的时候
  • VC中GDI绘图技术基础知识:hdc设备环境句柄,坐标系

    VC中GDI绘图技术 通过HDC设备环境句柄绘图有三种方式 标准客户区绘图 临时客户区绘图 非客户区绘图 1 标准客户区绘图 是在WM PAINT消息回调时执行 调用BeginPaint函数 EndPaint函数 2 临时客户区绘图 是在任
  • JSP+MVC开发模式 +EL表达式+ JSTL标签

    今日内容 1 JSP 1 指令 2 注释 3 内置对象 2 MVC开发模式 3 EL表达式 4 JSTL标签 5 三层架构 JSP 1 指令 作用 用于配置JSP页面 导入资源文件 格式 分类
  • ESP32 之 ESP-IDF 教学(十四)——虚拟文件系统(VFS)

    本文章 来自原创专栏 ESP32教学专栏 基于ESP IDF 讲解如何使用 ESP IDF 构建 ESP32 程序 发布文章并会持续为已发布文章添加新内容 每篇文章都经过了精打细磨 通过下方对话框进入专栏目录页 CSDN 请求进入目录 O
  • 安卓上基于透明代理抓包

    前言 在安卓上基于透明代理对特定APP抓包中使用的是redsocks2 本文演示如何使用clash实现同样的效果 你以为是Clash For Android 错 这里使用的是Core版本 就原理上来说 和前一篇文章并无区别 Clash的优势
  • Linux网络协议栈(五) -- 数据包的发送(based in 2.6.32)

    一 关键数据结构 对于输出封包 设备的数据结构主要包括两个 输出队列 queue 和输出队列规则 queue discipline 我们首先来看输出队列 2 6 18内核中无该结构体 struct netdev queue structne
  • 谈谈App混合开发

    混合开发的App Hybrid App 就是在一个App中内嵌一个轻量级的浏览器 一部分原生的功能改为Html 5来开发 这部分功能不仅能够在不升级App的情况下动态更新 而且可以在Android或iOS的App上同时运行 让用户的体验更好
  • 技术人修炼之道阅读笔记(六)解决对抗性思维方法

    技术人修炼之道阅读笔记 六 解决对抗性思维方法 网上经常看见产品经理和开发人员的段子 例如 杀死一个开发人员不用枪 只需要改三次需求 技术人开会 产品经理能安然无恙坐在这里 是因为门外有保安 等 这些都说明了产品经理和开发人员的矛盾 那么问
  • qt检查文件夹是否有写权限

    Qt 使用如下函数能够判断路径或者文件是否可写 bool QFileInfo isWritable const 对于win10系统实测 结果不准确 继续排查 官方文档描述 a 如果未启用 NTFS 权限检查 Windows 上的结果将仅反映
  • IDEA 程序包不存在,找不到符号但是明明存在对应的jar包 的解决方案

    注 本人刚开始是使用 Settings gt Build gt Build Tools gt Maven gt Runner gt 勾选上Delegagte IDE build run actions to Maven 这种办法 成功解决了
  • 内核管理-之进程虚拟内存-基于linux3.10

    关于启动过程内存管理见 内存管理 之启动 关于内核空间内存管理见 内存管理 之内核内存管理 如果需要 内存管理五章整理成pdf了 下载地址http download csdn net detail shichaog 8662135 进程的虚
  • hashmap 允许key重复吗_搞懂 HashMap,这一篇就够了

    HashMap 概述 如果你没有时间细抠本文 可以直接看 HashMap 概述 能让你对 HashMap 有个大致的了解 HashMap 是 Map 接口的实现 HashMap 允许空的 key value 键值对 HashMap 被认为是
  • Flutter页面关闭时Crash

    Flutter页面关闭时Crash 问题描述 项目中使用了Flutter的WebView组件来加载H5 关闭Activity时 如果FLutter页面中包含 WebView 就会导致Crash 页面中如果没有WebView 则正常关闭 Fl
  • 分布式一致性算法--Paxos

    分布式一致性算法 Paxos 2017 08 31 10 15 0人阅读 评论 0 收藏 编辑 删除 分类 Paxos 1 分布式一致性算法 Paxos Paxos算法是莱斯利 兰伯特 Leslie Lamport 1990年提出的一种基于
  • 深入探索Android稳定性优化

    前言 成为一名优秀的Android开发 需要一份完备的知识体系 在这里 让我们一起成长为自己所想的那样 众所周知 移动开发已经来到了后半场 为了能够在众多开发者中脱颖而出 我们需要对某一个领域有深入地研究与心得 对于Android开发者来说
  • Caffe解惑:为什么Caffe里头有mutable_cpu_data和cpu_data

    一开始看代码的时候会纳闷 为啥caffe里头又一个 cpu data 还要有一个mutable cpu data 其实从字面就可以看出来这个mutable就是易变的意思啦 二话不说翻出源代码看看究竟有啥区别 const void Synce
  • C# 入门教程

    C 简介 C 是一个简单的 现代的 通用的 面向对象的编程语言 它是由微软 Microsoft 开发的 下面列出了C 成为一种广泛应用的专业语言的原因 现代的 通用的编程语言 面向对象 面向组件 容易学习 结构化语言 它产生高效率的程序 它