湘阴网站设计,建站公司用哪家服务器,apmserv5.2.6 wordpress,变性 wordpressC#及其开发环境简介
C#概述
C#的编程功能
C#与.Net的关系
.Net
C#
C#的集成开发环境
Windows上编写C#程序
Linux/Mac OS上编写C#程序
运行第一个HelloWorld程序
C#基本语法
程序实例
C#基本语法
using关键字
class关键字
注释
成员变量
成员函数
实例化一个类…
C#及其开发环境简介
C#概述
C#的编程功能
C#与.Net的关系
.Net
C#
C#的集成开发环境
Windows上编写C#程序
Linux/Mac OS上编写C#程序
运行第一个HelloWorld程序
C#基本语法
程序实例
C#基本语法
using关键字
class关键字
注释
成员变量
成员函数
实例化一个类
标识符
C#关键字
C#占位符{}
C#数据类型
值类型
引用类型
对象(Object)类型
动态(Dynamic)类型
字符串(String)类型
指针类型
C#类型转换
C#类型转换方法
C#常量
整数常量
浮点常量
字符常量
字符串常量
定义常量
静态常量和动态常量
静态常量(编译时常量) const
动态常量(运行时常量) readonly
静态常量与动态常量的使用场景
C#运算符
算法运算符
关系运算符
逻辑运算符
位运算符
赋值运算符
其他运算符
C#中运算符的优先级
C#判断
if语句
if...else语句
嵌套if语句
switch语句
嵌套switch语句
?:运算符
C#循环
循环类型
while循环
for/foreach循环
do...while循环
循环控制语句
break语句
continue语句
无限循环
C#封装
C#方法
C#可空类型
C#数组
C#字符串
C#结构体
C#枚举 C#及其开发环境简介
C#概述
C# 是一个现代的、通用的、面向对象的编程语言它是由微软Microsoft开发的由 Ecma 和 ISO 核准认可的。
C# 是由 Anders Hejlsberg 和他的团队在 .Net 框架开发期间开发的。
C# 是专为公共语言基础结构CLI设计的。CLI 由可执行代码和运行时环境组成允许在不同的计算机平台和体系结构上使用各种高级语言。
下面列出了 C# 成为一种广泛应用的专业语言的原因
现代的、通用的编程语言。面向对象。面向组件。容易学习。结构化语言。它产生高效率的程序它可以在多种计算机平台上编译。.Net 框架的一部分。
C#的编程功能
虽然 C# 的构想十分接近于传统高级语言 C 和 C是一门面向对象的编程语言但是它与 Java 非常相似有许多强大的编程功能因此得到广大程序员的青睐。 下面列出 C# 一些重要的功能
布尔条件Boolean Conditions自动垃圾回收Automatic Garbage Collection标准库Standard Library组件版本Assembly Versioning属性Properties和事件Events委托Delegates和事件管理Events Management易于使用的泛型Generics索引器Indexers条件编译Conditional Compilation简单的多线程MultithreadingLINQ 和 Lambda 表达式集成 Windows
C#与.Net的关系
在这里主要讨论创建 C# 编程所需的工具。前面已经提到 C# 是 .Net 框架的一部分且用于编写 .Net 应用程序。因此在讨论运行 C# 程序的可用工具之前让我们先了解一下 C# 与 .Net 框架之间的关系。
.Net
NET是微软公司下的一个开发平台.NET核心就是.NET Framwork.NET框架是.NET程序开发和运行的环境在这个平台下可以用不同的语言进行开发因为.NET是跨语言的一个平台。语言可以是C#,f#,j#,vb.net等等。java和.NET不同的一点是java是跨平台的不跨语言的。.NET跨平台仅限于安卓系统和 iOS 苹果系统。 .Net 框架是一个创新的平台能帮您编写出下面类型的应用程序
Windows 应用程序Web 应用程序Web 服务
.Net 框架应用程序是多平台的应用程序。框架的设计方式使它适用于下列各种语言C#、C、Visual Basic、Jscript、COBOL 等等。所有这些语言可以访问框架彼此之间也可以互相交互。 .Net 框架由一个巨大的代码库组成用于 C# 等客户端语言。下面列出一些 .Net 框架的组件
公共语言运行库Common Language Runtime - CLR.Net 框架类库.Net Framework Class Library公共语言规范Common Language Specification通用类型系统Common Type System元数据Metadata和组件AssembliesWindows 窗体Windows FormsASP.Net 和 ASP.Net AJAXADO.NetWindows 工作流基础Windows Workflow Foundation - WFWindows 显示基础Windows Presentation FoundationWindows 通信基础Windows Communication Foundation - WCFLINQ
C#
C#是一个.NET平台下的一个程序设计语言仅仅是一个语言。是运行在.net CLR上的用于创建应用程序的高级语言。 程序设计语言是为了方便开发人员和计算机沟通的工具。
C#的集成开发环境
Windows上编写C#程序
微软Microsoft提供了下列用于 C# 编程的开发工具
Visual Studio 2010 (VS)Visual C# 2010 Express (VCE)Visual Web Developer
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。 VS 是 Visual Studio它是微软提供的一个工具集由各种各样的工具组成。VS 可以支持 C/C、VB、JAVA、C# 编程。然了一次只能支持一种编程方式。在 VS 安装完成第一次运行的时候会让你选择常用语言如果你选择 C/C那么他就成了能够进行 C/C 编程的平台也许就是你所说的 VC 了。如果不想用 C/C 的话只需要修改一下他的初始化设置选择别的编程语言就成为了另一种的语言的编程环境了。VC 是 Visual C是一个独立的 C/C 的开发工具比较著名的是 VC6.0现在的 VC2010其实就是 VC10.0。再通俗一点以 VS2010 和 VC2010 为例VS2010 相当与 Office2010包括了 World2010、Excel2010 等而 VC2010 就相当于是 World2010。 运行第一个HelloWorld程序
一个C#程序主要包含以下部分:
命名空间声明一个classClass方法Class属性一个Main方法语句表达式注释
C# 文件的后缀为 .cs。
以下创建一个 test.cs 文件文件包含了可以打印出 Hello World 的简单代码
using System;
namespace HelloWorldApplication
{class HelloWorld{static void Main(string[] args){/* 我的第一个 C# 程序*/Console.WriteLine(Hello World);Console.ReadKey();}}
}当上面的代码被编译和执行时它会产生下列结果
Hello World 程序的第一行using System:-using关键字用于在程序中包含System命名空间。一个程序一般有多个using语句。下一行是 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#基本语法
程序实例
C# 是一种面向对象的编程语言。在面向对象的程序设计方法中程序由各种相互交互的对象组成。相同种类的对象通常具有相同的类型或者说是在相同的 class 中。 例如以 Rectangle矩形对象为例。它具有 length 和 width 属性。根据设计它可能需要接受这些属性值、计算面积和显示细节。 让我们来看看一个 Rectangle矩形类的实现并借此讨论 C# 的基本语法
using System;
namespace RectangleApplication
{class Rectangle{// 成员变量int length;int width;public void Acceptdetails(){length 1; width 2;}public int 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){Rectangle r new Rectangle();r.Acceptdetails();r.Display();Console.ReadLine();}}
}运行结果 C#基本语法
using关键字
在任何 C# 程序中的第一条语句都是
using System;一般在程序开头添加 using System;这时System.String 就可简写为string 。 例如
// using System;namespace ConsoleApp1
{class Program{static void Main(string[] args){System.String a Hello World!;System.Console.WriteLine(a);System.Console.ReadKey();}}
}和
using System;namespace ConsoleApp1
{class Program{static void Main(string[] args){string a Hello World!;Console.WriteLine(a);Console.ReadKey();}}
}是等价的。using 关键字用于在程序中包含命名空间。一个程序可以包含多个 using 语句
class关键字
class关键字用于声明一个类
注释
注释是用于解释代码。编译器会忽略注释的条目。在 C# 程序中多行注释以/*开始并以字符 */ 终止如下所示
/* This program demonstrates
The basic syntax of C# programming
Language */单行注释是用 ‘//’ 符号表示。例如
}//end class Rectangle 成员变量
变量是类的属性或数据成员用于存储数据。在上面的程序中Rectangle 类有两个成员变量名为 length 和 width。
成员函数
函数是一系列执行指定任务的语句。类的成员函数是在类内声明的。我们举例的类 Rectangle 包含了三个成员函数 AcceptDetails、GetArea 和 Display。
实例化一个类
在上面的程序中类 ExecuteRectangle 是一个包含 Main() 方法和实例化 Rectangle 类的类。
Rectangle r new Rectangle();标识符
标识符是用来识别类、变量、函数或任何其它用户定义的项目。在 C# 中类的命名必须遵循如下基本规则
标识符必须以字母、下划线或 开头后面可以跟一系列的字母、数字 0 - 9 、下划线 _ 、。标识符中的第一个字符不能是数字。标识符必须不包含任何嵌入的空格或符号比如 ? - ! # % ^ * ( ) [ ] { } . ; : ’ / \。标识符不能是 C# 关键字。除非它们有一个 前缀。 例如if 是有效的标识符但 if 不是因为 if 是关键字。标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。不能与C#的类库名称相同。
C#关键字
关键字是 C# 编译器预定义的保留字。这些关键字不能用作标识符但是如果您想使用这些关键字作为标识符可以在关键字前面加上 字符作为前缀。 在 C# 中有些关键字在代码的上下文中有特殊的意义如 get 和 set这些被称为上下文关键字contextual keywords。 下表列出了 C# 中的保留关键字Reserved Keywords和上下文关键字Contextual Keywords C#占位符{}
当 WriteLine() 函数有多个参数时输出第一个参数(双引号内的)中的内容而第二个及后面的参数中的内容替换掉第一个参数中对应位置的占位符一起输出。
static void Main(string[] args)
{Console.WriteLine(A:{0}a:{1},65,97);Console.ReadLine();
}运行结果: 如果第一个参数没有留占位符那么第二个参数内容不输出
Console.WriteLine(A:,a:,65,97);运行结果 占位符从零开始计数,且占位符中的数字不能大于第二个及后面的参数的总个数减一(要求占位符必须有可替换的值)占位符数字与第二个及后面的参数字符位置一一对应。
static void Main(string[] args)
{Console.WriteLine(A:{1}a:{0},65,97);Console.ReadLine();
}C#数据类型
在C#中变量分为以下几种类型:
值类型Value types引用类型Reference types指针类型Pointer types
值类型
值类型变量可以直接分配给一个值。它们是从类 System.ValueType 中派生的。 值类型直接包含数据。比如 int、char、float它们分别存储数字、字符、浮点数。当您声明一个 int 类型时系统分配内存来存储值。 如需得到一个类型或一个变量在特定平台上的准确尺寸可以使用 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();}}
}引用类型
引用类型不包含存储在变量中的实际数据但它们包含对变量的引用。
换句话说它们指的是一个内存位置。使用多个变量时引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的其他变量会自动反映这种值的变化。内置的引用类型有object、dynamic 和 string。
对象(Object)类型
对象Object类型 是 C# 通用类型系统Common Type System - CTS中所有数据类型的终极基类。Object 是 System.Object 类的别名。所以对象Object类型可以被分配任何其他类型值类型、引用类型、预定义类型或用户自定义类型的值。但是在分配值之前需要先进行类型转换。当一个值类型转换为对象类型时则被称为 装箱另一方面当一个对象类型转换为值类型时则被称为 拆箱。
object obj;
obj 100; // 这是装箱
动态(Dynamic)类型
您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
声明动态类型的语法
dynamic variable_name value; 例如
dynamic d 20;
字符串(String)类型
字符串String类型 允许您给变量分配任何字符串值。字符串String类型是 System.String 类的别名。它是从对象Object类型派生的。字符串String类型的值可以通过两种形式进行分配引号和 引号。 例如
String str runoob.com;
一个 引号字符串
runoob.com; C# string 字符串的前面可以加 称作逐字字符串将转义字符\当作普通字符对待比如
string str C:\Windows; 等价于
string str C:\\Windows; 字符串中可以任意换行换行符及缩进空格都计算在字符串长度之内。
string str script typetext/javascript!----
/script; 用户自定义引用类型有class、interface 或 delegate。我们将在以后的章节中讨论这些类型。
指针类型
指针类型变量存储另一个类型的内存地址C#中的指针与C或C中的指针有相同的功能声明指针类型的语法:
type* identifier;例如:
char* cptr;
int* iptr;C#类型转换
类型转换从根本上说是类型铸造或者说是把数据从一种类型转换为另一种类型。在 C# 中类型铸造有两种形式
隐式类型转换 - 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如从小的整数类型转换为大的整数类型从派生类转换为基类。显式类型转换 - 显式类型转换即强制类型转换。显式转换需要强制转换运算符而且强制转换会造成数据丢失。
下面的实例显示了一个显式的类型转换
namespace TypeConversionApplication
{class ExplicitConversion{static void Main(string[] args){double d 5673.74;int i;// 强制转换 double 为 inti (int)d;Console.WriteLine(i);Console.ReadKey();}}
} 当上面的代码被编译和执行时它会产生下列结果
5673
C#类型转换方法
C# 提供了下列内置的类型转换方法 下面的实例把不同值的类型转换为字符串类型
namespace TypeConversionApplication
{class StringConversion{static void Main(string[] args){int i 75;float f 53.005f;double d 2345.7652;bool b true;Console.WriteLine(i.ToString());Console.WriteLine(f.ToString());Console.WriteLine(d.ToString());Console.WriteLine(b.ToString());Console.ReadKey();}} 当上面的代码被编译和执行时它会产生下列结果
75
53.005
2345.7652
True
C#常量
常量是固定值程序执行期间不会改变。常量可以是任何基本数据类型比如整数常量、浮点常量、字符常量或者字符串常量还有枚举常量。
常量可以被当作常规的变量只是它们的值在定义后不能被修改。
整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数0x 或 0X 表示十六进制0 表示八进制没有前缀则表示十进制。
整数常量也可以有后缀可以是 U 和 L 的组合其中U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写多个后缀以任意顺序进行组合。
这里有一些整数常量的实例
212 /* 合法 */
215u /* 合法 */
0xFeeL /* 合法 */
078 /* 非法8 不是一个八进制数字 */
032UU /* 非法不能重复后缀 */ 以下是各种类型的整数常量的实例
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* int */
30u /* 无符号 int */
30l /* long */
30ul /* 无符号 long */
浮点常量
一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
这里有一些浮点常量的实例
3.14159 /* 合法 */
314159E-5L /* 合法 */
510E /* 非法不完全指数 */
210f /* 非法没有小数或指数 */
.e55 /* 非法缺少整数或小数 */ 使用浮点形式表示时必须包含小数点、指数或同时包含两者。使用指数形式表示时必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。
字符常量
字符常量是括在单引号里例如‘x’且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符例如 ‘x’、一个转义序列例如 ‘\t’或者一个通用字符例如 ‘\u02C0’。 在 C# 中有一些特定的字符当它们的前面带有反斜杠时有特殊的意义可用于表示换行符\n或制表符 tab\t。在这里列出一些转义序列码
以下是一些转义序列字符的实例
namespace EscapeChar
{class Program{static void Main(string[] args){Console.WriteLine(Hello\tWorld\n\n);Console.ReadLine();}}
}
当上面的代码被编译和执行时它会产生下列结果
Hello World
字符串常量
字符串常量是括在双引号 里或者是括在 里。字符串常量包含的字符与字符常量相似可以是普通字符、转义序列和通用字符
使用字符串常量时可以把一个很长的行拆成多个行可以使用空格分隔各个部分。
这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。
string a hello, world; // hello, world
string b hello, world; // hello, world
string c hello \t world; // hello world
string d hello \t world; // hello \t world
string e Joe said \Hello\ to me; // Joe said Hello to me
string f Joe said Hello to me; // Joe said Hello to me
string g \\\\server\\share\\file.txt; // \\server\share\file.txt
string h \\server\share\file.txt; // \\server\share\file.txt
string i one\r\ntwo\r\nthree;
string j one
two
three;
定义常量
常量是使用 const 关键字来定义的 。定义一个常量的语法如下
const data_type constant_name value;下面的代码演示了如何在程序中定义和使用常量
using System;public class ConstTest
{class SampleClass{public int x;public int y;public const int c1 5;public const int c2 c1 5;public SampleClass(int p1, int p2){x p1;y p2;}}static void Main(){SampleClass mC new SampleClass(11, 22);Console.WriteLine(x {0}, y {1}, mC.x, mC.y);Console.WriteLine(c1 {0}, c2 {1},SampleClass.c1, SampleClass.c2);}
}结果:
x 11, y 22
c1 5, c2 10静态常量和动态常量
静态常量(编译时常量) const
在编译时就确定了值必须在声明时就进行初始化且之后不能进行更改可在类和方法中定义。定义方法如下
const double a3.14// 正确声明常量的方法
const int b; // 错误没有初始化动态常量(运行时常量) readonly
在运行时确定值只能在声明时或构造函数中初始化只能在类中定义。定义方法如下
class Program
{readonly int a1; // 声明时初始化readonly int b; // 构造函数中初始化Program(){b2;}static void Main(){}
}静态常量与动态常量的使用场景
在下面两种情况下可以使用 const 常量
取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)。对程序性能要求非常苛刻。
除此之外的其他情况都应该优先采用 readonly 常量。
C#运算符
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符分类如下
算术运算符关系运算符逻辑运算符位运算符赋值运算符其他运算符
算法运算符
下表显示了 C# 支持的所有算术运算符。假设变量 A 的值为 10变量 B 的值为 20则 实例:
请看下面的实例了解 C# 中所有可用的算术运算符
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){int a 21;int b 10;int c;c a b;Console.WriteLine(Line 1 - c 的值是 {0}, c);c a - b;Console.WriteLine(Line 2 - c 的值是 {0}, c);c a * b;Console.WriteLine(Line 3 - c 的值是 {0}, c);c a / b;Console.WriteLine(Line 4 - c 的值是 {0}, c);c a % b;Console.WriteLine(Line 5 - c 的值是 {0}, c);// a 先进行自增运算再赋值c a;Console.WriteLine(Line 6 - c 的值是 {0}, c);// 此时 a 的值为 22// --a 先进行自减运算再赋值c --a;Console.WriteLine(Line 7 - c 的值是 {0}, c);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
Line 1 - c 的值是 31
Line 2 - c 的值是 11
Line 3 - c 的值是 210
Line 4 - c 的值是 2
Line 5 - c 的值是 1
Line 6 - c 的值是 22
Line 7 - c 的值是 21
c a: 先将 a 赋值给 c再对 a 进行自增运算。c a: 先将 a 进行自增运算再将 a 赋值给 c 。c a--: 先将 a 赋值给 c再对 a 进行自减运算。c --a: 先将 a 进行自减运算再将 a 赋值给 c 。
实例
using System;namespace OperatorsAppl
{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; // 重新初始化 ab a;Console.WriteLine(a {0}, a);Console.WriteLine(b {0}, b);Console.ReadLine();// a-- 先赋值再进行自减运算a 1; // 重新初始化 ab a--;Console.WriteLine(a {0}, a);Console.WriteLine(b {0}, b);Console.ReadLine();// --a 先进行自减运算再赋值a 1; // 重新初始化 ab --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变量 B 的值为 20则
实例
请看下面的实例了解 C# 中所有可用的关系运算符
using System;class Program
{static void Main(string[] args){int a 21;int b 10;if (a b){Console.WriteLine(Line 1 - a 等于 b);}else{Console.WriteLine(Line 1 - a 不等于 b);}if (a b){Console.WriteLine(Line 2 - a 小于 b);}else{Console.WriteLine(Line 2 - a 不小于 b);}if (a b){Console.WriteLine(Line 3 - a 大于 b);}else{Console.WriteLine(Line 3 - a 不大于 b);}/* 改变 a 和 b 的值 */a 5;b 20;if (a b){Console.WriteLine(Line 4 - a 小于或等于 b);}if (b a){Console.WriteLine(Line 5 - b 大于或等于 a);}}
}
结果
Line 1 - a 不等于 b
Line 2 - a 不小于 b
Line 3 - a 大于 b
Line 4 - a 小于或等于 b
Line 5 - b 大于或等于 a
逻辑运算符
下表显示了 C# 支持的所有逻辑运算符。假设变量 A 为布尔值 true变量 B 为布尔值 false则 实例 请看下面的实例了解 C# 中所有可用的逻辑运算符
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){bool a true;bool b true;if (a b){Console.WriteLine(Line 1 - 条件为真);}if (a || b){Console.WriteLine(Line 2 - 条件为真);}/* 改变 a 和 b 的值 */a false;b true;if (a b){Console.WriteLine(Line 3 - 条件为真);}else{Console.WriteLine(Line 3 - 条件不为真);}if (!(a b)){Console.WriteLine(Line 4 - 条件为真);}Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
Line 1 - 条件为真
Line 2 - 条件为真
Line 3 - 条件不为真
Line 4 - 条件为真
位运算符
位运算符作用于位并逐位执行操作。、 | 和 ^ 的真值表如下所示 假设如果 A 60且 B 13现在以二进制格式表示它们如下所示
A 0011 1100
B 0000 1101
-----------------
AB 0000 1100
A|B 0011 1101
A^B 0011 0001
~A 1100 0011
下表列出了 C# 支持的位运算符。假设变量 A 的值为 60变量 B 的值为 13则 实例
using System;
namespace OperatorsAppl
{class Program{static void Main(string[] args){int a 60; /* 60 0011 1100 */ int b 13; /* 13 0000 1101 */int c 0; c a b; /* 12 0000 1100 */Console.WriteLine(Line 1 - c 的值是 {0}, c );c a | b; /* 61 0011 1101 */Console.WriteLine(Line 2 - c 的值是 {0}, c);c a ^ b; /* 49 0011 0001 */Console.WriteLine(Line 3 - c 的值是 {0}, c);c ~a; /*-61 1100 0011 */Console.WriteLine(Line 4 - c 的值是 {0}, c);c a 2; /* 240 1111 0000 */Console.WriteLine(Line 5 - c 的值是 {0}, c);c a 2; /* 15 0000 1111 */Console.WriteLine(Line 6 - c 的值是 {0}, c);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15
赋值运算符
下表列出了 C# 支持的赋值运算符 实例 using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){int a 21;int c;c a;Console.WriteLine(Line 1 - c 的值 {0}, c);c a;Console.WriteLine(Line 2 - c 的值 {0}, c);c - a;Console.WriteLine(Line 3 - - c 的值 {0}, c);c * a;Console.WriteLine(Line 4 - * c 的值 {0}, c);c / a;Console.WriteLine(Line 5 - / c 的值 {0}, c);c 200;c % a;Console.WriteLine(Line 6 - % c 的值 {0}, c);c 2;Console.WriteLine(Line 7 - c 的值 {0}, c);c 2;Console.WriteLine(Line 8 - c 的值 {0}, c);c 2;Console.WriteLine(Line 9 - c 的值 {0}, c);c ^ 2;Console.WriteLine(Line 10 - ^ c 的值 {0}, c);c | 2;Console.WriteLine(Line 11 - | c 的值 {0}, c);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
Line 1 - c 的值 21
Line 2 - c 的值 42
Line 3 - - c 的值 21
Line 4 - * c 的值 441
Line 5 - / c 的值 21
Line 6 - % c 的值 11
Line 7 - c 的值 44
Line 8 - c 的值 11
Line 9 - c 的值 2
Line 10 - ^ c 的值 0
Line 11 - | c 的值 2
其他运算符
下表列出了 C# 支持的其他一些重要的运算符包括 sizeof、typeof 和 ? :。 实例
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){/* sizeof 运算符的实例 */Console.WriteLine(int 的大小是 {0}, sizeof(int));Console.WriteLine(short 的大小是 {0}, sizeof(short));Console.WriteLine(double 的大小是 {0}, sizeof(double));/* 三元运算符的实例 */int a, b;a 10;b (a 1) ? 20 : 30;Console.WriteLine(b 的值是 {0}, b);b (a 10) ? 20 : 30;Console.WriteLine(b 的值是 {0}, b);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
int 的大小是 4
short 的大小是 2
double 的大小是 8
b 的值是 30
b 的值是 20
C#中运算符的优先级
运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级例如乘除运算符具有比加减运算符更高的优先级。
例如 x 7 3 * 2在这里x 被赋值为 13而不是 20因为运算符 * 具有比 更高的优先级所以首先计算乘法 3*2然后再加上 7。
下表将按运算符优先级从高到低列出各个运算符具有较高优先级的运算符出现在表格的上面具有较低优先级的运算符出现在表格的下面。在表达式中较高优先级的运算符会优先被计算。 实例
using System;namespace OperatorsAppl
{class Program{static void Main(string[] args){int a 20;int b 10;int c 15;int d 5;int e;e (a b) * c / d; // ( 30 * 15 ) / 5Console.WriteLine((a b) * c / d 的值是 {0}, e);e ((a b) * c) / d; // (30 * 15 ) / 5Console.WriteLine(((a b) * c) / d 的值是 {0}, e);e (a b) * (c / d); // (30) * (15/5)Console.WriteLine((a b) * (c / d) 的值是 {0}, e);e a (b * c) / d; // 20 (150/5)Console.WriteLine(a (b * c) / d 的值是 {0}, e);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
(a b) * c / d 的值是 90
((a b) * c) / d 的值是 90
(a b) * (c / d) 的值是 90
a (b * c) / d 的值是 50
C#判断
判断结构要求程序员指定一个或多个要评估或测试的条件以及条件为真时要执行的语句必需的和条件为假时要执行的语句可选的。
判断语句
C# 提供了以下类型的判断语句。
if语句
一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。
语法
C# 中 if 语句的语法
if(boolean_expression)
{/* 如果布尔表达式为真将执行的语句 */
} 如果布尔表达式为 true则 if 语句内的代码块将被执行。如果布尔表达式为 false则 if 语句结束后的第一组代码闭括号后将被执行。
实例
using System;namespace DecisionMaking
{class Program{static void Main(string[] args){/* 局部变量定义 */int a 10;/* 使用 if 语句检查布尔条件 */if (a 20){/* 如果条件为真则输出下面的语句 */Console.WriteLine(a 小于 20);}Console.WriteLine(a 的值是 {0}, a);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果 if...else语句
一个 if 语句 后可跟一个可选的 else 语句else 语句在布尔表达式为假时执行。
语法
C# 中 if...else 语句的语法
if(boolean_expression)
{/* 如果布尔表达式为真将执行的语句 */
}
else
{/* 如果布尔表达式为假将执行的语句 */
} 如果布尔表达式为 true则执行 if 块内的代码。如果布尔表达式为 false则执行 else 块内的代码。
实例
using System;namespace DecisionMaking
{class Program{static void Main(string[] args){/* 局部变量定义 */int a 100;/* 检查布尔条件 */if (a 20){/* 如果条件为真则输出下面的语句 */Console.WriteLine(a 小于 20);}else{/* 如果条件为假则输出下面的语句 */Console.WriteLine(a 大于 20);}Console.WriteLine(a 的值是 {0}, a);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果 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 将不会被测试。
C# 中的 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 语句。
C# 中 嵌套 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 进行检查
C# 中 switch 语句的语法
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 常量包含共同的值也没有矛盾。
C# 中 嵌套 switch 语句的语法
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 循环语句会重复执行一个目标语句。、
C# 中 while 循环的语法
while(condition)
{statement(s);
} 在这里statement(s) 可以是一个单独的语句也可以是几个语句组成的代码块。condition 可以是任意的表达式当为任意非零值时都为真。当条件为真时执行循环。
当条件为假时程序流将继续执行紧接着循环的下一条语句。
在这里while 循环的关键点是循环可能一次都不会执行。当条件被测试且结果为假时会跳过循环主体直接执行紧接着 while 循环的下一条语句。
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 循环是一个允许您编写一个执行特定次数的循环的重复控制结构。
C# 中 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 foreach
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
130
1
1
2
3
5
8
13Element #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
do...while循环
不像 for 和 while 循环它们是在循环头部测试循环条件。do...while 循环是在循环的尾部检查它的条件。
do...while 循环与 while 循环类似但是 do...while 循环会确保至少执行一次循环。
C# 中 do...while 循环的语法
do
{statement(s);}while( condition );
请注意条件表达式出现在循环的尾部所以循环中的 statement(s) 会在条件被测试之前至少执行一次。
如果条件为真控制流会跳转回上面的 do然后重新执行循环中的 statement(s)。这个过程会不断重复直到给定条件变为假为止。
实例
using System;namespace Loops
{class Program{static void Main(string[] args){/* 局部变量定义 */int a 10;/* do 循环执行 */do{Console.WriteLine(a 的值 {0}, a);a a 1;} while (a 20);Console.ReadLine();}} 当上面的代码被编译和执行时它会产生下列结果
a 的值 10
a 的值 11
a 的值 12
a 的值 13
a 的值 14
a 的值 15
a 的值 16
a 的值 17
a 的值 18
a 的值 19
循环控制语句
break语句
C# 中 break 语句有以下两种用法 当 break 语句出现在一个循环内时循环会立即终止且程序流将继续执行紧接着循环的下一条语句。 它可用于终止 switch 语句中的一个 case。
如果您使用的是嵌套循环即一个循环内嵌套另一个循环break 语句会停止执行最内层的循环然后开始执行该块之后的下一行代码。
C# 中 break 语句的语法
break; 实例
using System;namespace Loops
{class Program{static void Main(string[] args){/* 局部变量定义 */int a 10;/* while 循环执行 */while (a 20){Console.WriteLine(a 的值 {0}, a);a;if (a 15){/* 使用 break 语句终止 loop */break;}}Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
a 的值 10
a 的值 11
a 的值 12
a 的值 13
a 的值 14
a 的值 15
continue语句
C# 中的 continue 语句有点像 break 语句。但它不是强迫终止continue 会跳过当前循环中的代码强迫开始下一次循环。
对于 for 循环continue 语句会导致执行条件测试和循环增量部分。对于 while 和 do...while 循环continue 语句会导致程序控制回到条件测试上。
using System;namespace Loops
{class Program{static void Main(string[] args){/* 局部变量定义 */int a 10;/* do 循环执行 */do{if (a 15){/* 跳过迭代 */a a 1;continue;}Console.WriteLine(a 的值 {0}, a);a;} while (a 20);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
a 的值 10
a 的值 11
a 的值 12
a 的值 13
a 的值 14
a 的值 16
a 的值 17
a 的值 18
a 的值 19
无限循环
如果条件永远不为假则循环将变成无限循环。for 循环在传统意义上可用于实现无限循环。由于构成循环的三个表达式中任何一个都不是必需的您可以将某些条件表达式留空来构成一个无限循环。
using System;namespace Loops
{class Program{static void Main(string[] args){for (; ; ){Console.WriteLine(Hey! I am Trapped);}}}
} 当条件表达式不存在时它被假设为真。您也可以设置一个初始值和增量表达式但是一般情况下程序员偏向于使用 for(;;) 结构来表示一个无限循环。
C#封装
封装 被定义为把一个或多个项目封闭在一个物理的或者逻辑的包中。在面向对象程序设计方法论中封装是为了防止对实现细节的访问。
抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可视化封装则使开发者实现所需级别的抽象。
C# 封装根据具体的需要设置使用者的访问权限并通过 访问修饰符 来实现。
一个 访问修饰符 定义了一个类成员的范围和可见性。C# 支持的访问修饰符如下所示
public所有对象都可以访问private对象本身在对象内部可以访问protected只有该类对象及其子类对象可以访问internal同一个程序集的对象可以访问protected internal访问限于当前程序集或派生自包含类的类型。
Public 访问修饰符
Public 访问修饰符允许一个类将其成员变量和成员函数暴露给其他的函数和对象。任何公有成员可以被外部的类访问。
下面的实例说明了这点
using System;namespace RectangleApplication
{class Rectangle{//成员变量public double length;public double width;public double GetArea(){return length * width;}public void Display(){Console.WriteLine(长度 {0}, length);Console.WriteLine(宽度 {0}, width);Console.WriteLine(面积 {0}, GetArea());}}// Rectangle 结束class ExecuteRectangle{static void Main(string[] args){Rectangle r new Rectangle();r.length 4.5;r.width 3.5;r.Display();Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果 长度 4.5
宽度 3.5
面积 15.75 在上面的实例中成员变量 length 和 width 被声明为 public所以它们可以被函数 Main() 使用 Rectangle 类的实例 r 访问。
成员函数 Display() 和 GetArea() 可以直接访问这些变量。
成员函数 Display() 也被声明为 public所以它也能被 Main() 使用 Rectangle 类的实例 r 访问。
private访问修饰符
Private 访问修饰符允许一个类将其成员变量和成员函数对其他的函数和对象进行隐藏。只有同一个类中的函数可以访问它的私有成员。即使是类的实例也不能访问它的私有成员。
下面的实例说明了这点
using System;namespace RectangleApplication
{class Rectangle{//成员变量private double length;private double width;public void Acceptdetails(){Console.WriteLine(请输入长度);length Convert.ToDouble(Console.ReadLine());Console.WriteLine(请输入宽度);width Convert.ToDouble(Console.ReadLine());}public double GetArea(){return length * width;}public void Display(){Console.WriteLine(长度 {0}, length);Console.WriteLine(宽度 {0}, width);Console.WriteLine(面积 {0}, GetArea());}}//end class Rectangle class ExecuteRectangle{static void Main(string[] args){Rectangle r new Rectangle();r.Acceptdetails();r.Display();Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
请输入长度
4.4
请输入宽度
3.3
长度 4.4
宽度 3.3
面积 14.52 在上面的实例中成员变量 length 和 width 被声明为 private所以它们不能被函数 Main() 访问。
成员函数 AcceptDetails() 和 Display() 可以访问这些变量。
由于成员函数 AcceptDetails() 和 Display() 被声明为 public所以它们可以被 Main() 使用 Rectangle 类的实例 r 访问。
protected访问修饰符
Protected 访问修饰符允许子类访问它的基类的成员变量和成员函数。这样有助于实现继承。我们将在继承的章节详细讨论这个。更详细地讨论这个。
lnternal访问修饰符
Internal 访问说明符允许一个类将其成员变量和成员函数暴露给当前程序中的其他函数和对象。换句话说带有 internal 访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问。
下面的实例说明了这点
using System;namespace RectangleApplication
{class Rectangle{//成员变量internal double length;internal double width;double GetArea(){return length * width;}public void Display(){Console.WriteLine(长度 {0}, length);Console.WriteLine(宽度 {0}, width);Console.WriteLine(面积 {0}, GetArea());}}//end class Rectangle class ExecuteRectangle{static void Main(string[] args){Rectangle r new Rectangle();r.length 4.5;r.width 3.5;r.Display();Console.ReadLine();}}
}
当上面的代码被编译和执行时它会产生下列结果
长度 4.5
宽度 3.5
面积 15.75
在上面的实例中请注意成员函数 GetArea() 声明的时候不带有任何访问修饰符。如果没有指定访问修饰符则使用类成员的默认访问修饰符即为 private。
protected lnternal访问修饰符
Protected Internal 访问修饰符允许在本类,派生类或者包含该类的程序集中访问。这也被用于实现继承。 比如说一个人A为父类他的儿子B妻子C私生子D注D不在他家里 如果我们给A的事情增加修饰符 public事件地球人都知道全公开protected事件ABD知道A和他的所有儿子知道妻子C不知道 private事件只有A知道隐私心事internal事件ABC知道A家里人都知道私生子D不知道 protected internal事件ABCD都知道,其它人不知道 (1) Pubilc 任何公有成员可以被外部的类访问。
(2) Private 只有同一个类中的函数可以访问它的私有成员。 (3) Protected 该类内部和继承类中可以访问。
(4) internal : 同一个程序集的对象可以访问。
(5) Protected internal 3 和 4 的并集符合任意一条都可以访问。
C#方法
一个方法是把一些相关的语句组织在一起用来执行一个任务的语句块。每一个 C# 程序至少有一个带有 Main 方法的类。
要使用一个方法您需要
定义方法调用方法
当定义一个方法时从根本上说是在声明它的结构的元素。在 C# 中定义方法的语法如下
Access Specifier Return Type Method Name(Parameter List)
{Method Body
} 下面是方法的各个元素
Access Specifier访问修饰符这个决定了变量或方法对于另一个类的可见性。Return type返回类型一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值则返回类型为 void。Method name方法名称是一个唯一的标识符且是大小写敏感的。它不能与类中声明的其他标识符相同。Parameter list参数列表使用圆括号括起来该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的也就是说一个方法可能不包含参数。Method body方法主体包含了完成任务所需的指令集。
class NumberManipulator
{public int FindMax(int num1, int num2){/* 局部变量声明 */int result;if (num1 num2)result num1;elseresult num2;return result;}...
} C#调用方法
您可以使用方法名调用方法。下面的实例演示了这点
using System;namespace CalculatorApplication
{class NumberManipulator{public int FindMax(int num1, int num2){/* 局部变量声明 */int result;if (num1 num2)result num1;elseresult num2;return result;}static void Main(string[] args){/* 局部变量定义 */int a 100;int b 200;int ret;NumberManipulator n new NumberManipulator();//调用 FindMax 方法ret n.FindMax(a, b);Console.WriteLine(最大值是 {0}, ret );Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
最大值是 200 您也可以使用类的实例从另一个类中调用其他类的公有方法。例如方法 FindMax 属于 NumberManipulator 类您可以从另一个类 Test 中调用它。
using System;namespace CalculatorApplication
{class NumberManipulator{public int FindMax(int num1, int num2){/* 局部变量声明 */int result;if (num1 num2)result num1;elseresult num2;return result;}}class Test{static void Main(string[] args){/* 局部变量定义 */int a 100;int b 200;int ret;NumberManipulator n new NumberManipulator();//调用 FindMax 方法ret n.FindMax(a, b);Console.WriteLine(最大值是 {0}, ret );Console.ReadLine();}}
}
当上面的代码被编译和执行时它会产生下列结果
最大值是 200 递归方法调用
一个方法可以自我调用。这就是所谓的 递归。下面的实例使用递归函数计算一个数的阶乘
using System;namespace CalculatorApplication
{class NumberManipulator{public int factorial(int num){/* 局部变量定义 */int result;if (num 1){return 1;}else{result factorial(num - 1) * num;return result;}}static void Main(string[] args){NumberManipulator n new NumberManipulator();//调用 factorial 方法Console.WriteLine(6 的阶乘是 {0}, n.factorial(6));Console.WriteLine(7 的阶乘是 {0}, n.factorial(7));Console.WriteLine(8 的阶乘是 {0}, n.factorial(8));Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
6 的阶乘是 720
7 的阶乘是 5040
8 的阶乘是 40320 参数传递
当调用带有参数的方法时您需要向方法传递参数。在 C# 中有三种向方法传递参数的方式 按值传递参数
这是参数传递的默认方式。在这种方式下当调用一个方法时会为每个值参数创建一个新的存储位置。
实际参数的值会复制给形参实参和形参使用的是两个不同内存中的值。所以当形参的值发生改变时不会影响实参的值从而保证了实参数据的安全。下面的实例演示了这个概念
using System;
namespace CalculatorApplication
{class NumberManipulator{public void swap(int x, int y){int temp;temp x; /* 保存 x 的值 */x y; /* 把 y 赋值给 x */y temp; /* 把 temp 赋值给 y */}static void Main(string[] args){NumberManipulator n new NumberManipulator();/* 局部变量定义 */int a 100;int b 200;Console.WriteLine(在交换之前a 的值 {0}, a);Console.WriteLine(在交换之前b 的值 {0}, b);/* 调用函数来交换值 */n.swap(a, b);Console.WriteLine(在交换之后a 的值 {0}, a);Console.WriteLine(在交换之后b 的值 {0}, b);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
在交换之前a 的值100
在交换之前b 的值200
在交换之后a 的值100
在交换之后b 的值200
结果表明即使在函数内改变了值值也没有发生任何的变化。
按引用传递参数
引用参数是一个对变量的内存位置的引用。当按引用传递参数时与值参数不同的是它不会为这些参数创建一个新的存储位置。引用参数表示与提供给方法的实际参数具有相同的内存位置。
在 C# 中使用 ref 关键字声明引用参数。下面的实例演示了这点
using System;
namespace CalculatorApplication
{class NumberManipulator{public void swap(ref int x, ref int y){int temp;temp x; /* 保存 x 的值 */x y; /* 把 y 赋值给 x */y temp; /* 把 temp 赋值给 y */}static void Main(string[] args){NumberManipulator n new NumberManipulator();/* 局部变量定义 */int a 100;int b 200;Console.WriteLine(在交换之前a 的值 {0}, a);Console.WriteLine(在交换之前b 的值 {0}, b);/* 调用函数来交换值 */n.swap(ref a, ref b);Console.WriteLine(在交换之后a 的值 {0}, a);Console.WriteLine(在交换之后b 的值 {0}, b);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
在交换之前a 的值100
在交换之前b 的值200
在交换之后a 的值200
在交换之后b 的值100 结果表明swap 函数内的值改变了且这个改变可以在 Main 函数中反映出来。
按输出传递参数
return 语句可用于只从函数中返回一个值。但是可以使用 输出参数 来从函数中返回两个值。输出参数会把方法输出的数据赋给自己其他方面与引用参数相似。
下面的实例演示了这点
using System;namespace CalculatorApplication
{class NumberManipulator{public void getValue(out int x ){int temp 5;x temp;}static void Main(string[] args){NumberManipulator n new NumberManipulator();/* 局部变量定义 */int a 100;Console.WriteLine(在方法调用之前a 的值 {0}, a);/* 调用函数来获取值 */n.getValue(out a);Console.WriteLine(在方法调用之后a 的值 {0}, a);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
在方法调用之前a 的值 100
在方法调用之后a 的值 5 提供给输出参数的变量不需要赋值。当需要从一个参数没有指定初始值的方法中返回值时输出参数特别有用。请看下面的实例来理解这一点
using System;namespace CalculatorApplication
{class NumberManipulator{public void getValues(out int x, out int y ){Console.WriteLine(请输入第一个值 );x Convert.ToInt32(Console.ReadLine());Console.WriteLine(请输入第二个值 );y Convert.ToInt32(Console.ReadLine());}static void Main(string[] args){NumberManipulator n new NumberManipulator();/* 局部变量定义 */int a , b;/* 调用函数来获取值 */n.getValues(out a, out b);Console.WriteLine(在方法调用之后a 的值 {0}, a);Console.WriteLine(在方法调用之后b 的值 {0}, b);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果取决于用户输入
请输入第一个值
7
请输入第二个值
8
在方法调用之后a 的值 7
在方法调用之后b 的值 8
C#可空类型
C#单问号?与双问号??
? 单问号用于对 int、double、bool 等无法直接赋值为 null 的数据类型进行 null 的赋值意思是这个数据类型是 Nullable 类型的。
int? i 3; 等同于
Nullableint i new Nullableint(3);
int i; //默认值0
int? ii; //默认值null ?? 双问号用于判断一个变量在为 null 的时候返回一个指定的值。
接下来我们详细说明。
C#可空类型
C# 提供了一个特殊的数据类型nullable 类型可空类型可空类型可以表示其基础值类型正常范围内的值再加上一个 null 值。
例如Nullable Int32 读作可空的 Int32可以被赋值为 -2,147,483,648 到 2,147,483,647 之间的任意值也可以被赋值为 null 值。类似的Nullable bool 变量可以被赋值为 true 或 false 或 null。
在处理数据库和其他包含可能未赋值的元素的数据类型时将 null 赋值给数值类型或布尔型的功能特别有用。例如数据库中的布尔型字段可以存储值 true 或 false或者该字段也可以未定义。
声明一个 nullable 类型可空类型的语法如下 data_type ? variable_name null; 下面的实例演示了可空数据类型的用法
using System;
namespace CalculatorApplication
{class NullablesAtShow{static void Main(string[] args){int? num1 null;int? num2 45;double? num3 new double?();double? num4 3.14157;bool? boolval new bool?();// 显示值Console.WriteLine(显示可空类型的值 {0}, {1}, {2}, {3},num1, num2, num3, num4);Console.WriteLine(一个可空的布尔值 {0}, boolval);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
显示可空类型的值 , 45, , 3.14157
一个可空的布尔值
Null合并运算符(??
Null 合并运算符用于定义可空类型和引用类型的默认值。Null 合并运算符为类型转换定义了一个预设值以防可空类型的值为 Null。Null 合并运算符把操作数类型隐式转换为另一个可空或不可空的值类型的操作数的类型。
如果第一个操作数的值为 null则运算符返回第二个操作数的值否则返回第一个操作数的值。下面的实例演示了这点
using System;
namespace CalculatorApplication
{class NullablesAtShow{static void Main(string[] args){double? num1 null;double? num2 3.14157;double num3;num3 num1 ?? 5.34; // num1 如果为空值则返回 5.34Console.WriteLine(num3 的值 {0}, num3);num3 num2 ?? 5.34;Console.WriteLine(num3 的值 {0}, num3);Console.ReadLine();}}
} 当上面的代码被编译和执行时它会产生下列结果
num3 的值 5.34
num3 的值 3.14157
C#数组
数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合通常认为数组是一个同一类型变量的集合。
声明数组变量并不是声明 number0、number1、...、number99 一个个单独的变量而是声明一个就像 numbers 这样的变量然后使用 numbers[0]、numbers[1]、...、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。
所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素最高的地址对应最后一个元素。
声明数组
在 C# 中声明一个数组您可以使用下面的语法
datatype[] arrayName; 其中
datatype 用于指定被存储在数组中的元素的类型。[ ] 指定数组的秩维度。秩指定数组的大小。arrayName 指定数组的名称。
例如
double[] balance;
初始化数组
声明一个数组不会在内存中初始化数组。当初始化数组变量时您可以赋值给数组。
数组是一个引用类型所以您需要使用 new 关键字来创建数组的实例。
例如
double[] balance new double[10];
赋值给数组 您可以通过使用索引号赋值给一个单独的数组元素比如
double[] balance new double[10];
balance[0] 4500.0; 您可以在声明数组的同时给数组赋值比如
double[] balance { 2340.0, 4523.69, 3421.0}; 您也可以创建并初始化一个数组比如
int [] marks new int[5] { 99, 98, 92, 97, 95}; 在上述情况下你也可以省略数组的大小比如
int [] marks new int[] { 99, 98, 92, 97, 95}; 您也可以赋值一个数组变量到另一个目标数组变量中。在这种情况下目标和源会指向相同的内存位置
int [] marks new int[] { 99, 98, 92, 97, 95};
int[] score marks; 当您创建一个数组时C# 编译器会根据数组类型隐式初始化每个数组元素为一个默认值。例如int 数组的所有元素都会被初始化为 0。
访问数组元素
元素是通过带索引的数组名称来访问的。这是通过把元素的索引放置在数组名称后的方括号中来实现的。例如’
double salary balance[9]; 下面是一个实例使用上面提到的三个概念即声明、赋值、访问数组
using System;
namespace ArrayApplication
{class MyArray{static void Main(string[] args){int [] n new int[10]; /* n 是一个带有 10 个整数的数组 */int i,j;/* 初始化数组 n 中的元素 */ for ( i 0; i 10; i ){n[ i ] i 100;}/* 输出每个数组元素的值 */for (j 0; j 10; j ){Console.WriteLine(Element[{0}] {1}, j, n[j]);}Console.ReadKey();}}
} 当上面的代码被编译和执行时它会产生下列结果
Element[0] 100
Element[1] 101
Element[2] 102
Element[3] 103
Element[4] 104
Element[5] 105
Element[6] 106
Element[7] 107
Element[8] 108
Element[9] 109
使用foreach循环
在前面的实例中我们使用一个 for 循环来访问每个数组元素。您也可以使用一个 foreach 语句来遍历数组。
using System;namespace ArrayApplication
{class MyArray{static void Main(string[] args){int [] n new int[10]; /* n 是一个带有 10 个整数的数组 *//* 初始化数组 n 中的元素 */ for ( int i 0; i 10; i ){n[i] i 100;}/* 输出每个数组元素的值 */foreach (int j in n ){int i j-100;Console.WriteLine(Element[{0}] {1}, i, j);}Console.ReadKey();}}
} 当上面的代码被编译和执行时它会产生下列结果
Element[0] 100
Element[1] 101
Element[2] 102
Element[3] 103
Element[4] 104
Element[5] 105
Element[6] 106
Element[7] 107
Element[8] 108
Element[9] 109 C#字符串
在 C# 中您可以使用字符数组来表示字符串但是更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字是 System.String 类的别名。
您可以使用以下方法之一来创建 string 对象
通过给 String 变量指定一个字符串通过使用 String 类构造函数通过使用字符串串联运算符 通过检索属性或调用一个返回字符串的方法通过格式化方法来转换一个值或对象为它的字符串表示形式
下面的实例演示了这点
using System;namespace StringApplication
{class Program{static void Main(string[] args){//字符串字符串连接string fname, lname;fname Rowan;lname Atkinson;string fullname fname lname;Console.WriteLine(Full Name: {0}, fullname);//通过使用 string 构造函数char[] letters { H, e, l, l,o };string greetings new string(letters);Console.WriteLine(Greetings: {0}, greetings);//方法返回字符串string[] sarray { Hello, From, Tutorials, Point };string message String.Join( , sarray);Console.WriteLine(Message: {0}, message);//用于转化值的格式化方法DateTime waiting new DateTime(2012, 10, 10, 17, 58, 1);string chat String.Format(Message sent at {0:t} on {0:D},waiting);Console.WriteLine(Message: {0}, chat);Console.ReadKey() ;}}
} 当上面的代码被编译和执行时它会产生下列结果
Full Name: RowanAtkinson
Greetings: Hello
Message: Hello From Tutorials Point
Message: Message sent at 17:58 on Wednesday, 10 October 2012
string类的属性
String 类有以下两个属性 string类的方法
String 类有许多方法用于 string 对象的操作。下面的表格提供了一些最常用的方法 实例
下面的实例演示了上面提到的一些方法
比较字符串 using System;namespace StringApplication
{class StringProg{static void Main(string[] args){string str1 This is test;string str2 This is text;if (String.Compare(str1, str2) 0){Console.WriteLine(str1 and str2 are equal.);}else{Console.WriteLine(str1 and str2 are not equal.);}Console.ReadKey() ;}}
} 当上面的代码被编译和执行时它会产生下列结果
This is test and This is text are not equal. 字符串包含字符串
using System;namespace StringApplication
{class StringProg{static void Main(string[] args){string str This is test;if (str.Contains(test)){Console.WriteLine(The sequence test was found.);}Console.ReadKey() ;}}
} 当上面的代码被编译和执行时它会产生下列结果
The sequence test was found. 获取子字符串
using System;
namespace StringApplication
{class StringProg{static void Main(string[] args){string str Last night I dreamt of San Pedro;Console.WriteLine(str);string substr str.Substring(23);Console.WriteLine(substr);Console.ReadKey() ;}}
} 当上面的代码被编译和执行时它会产生下列结果
Last night I dreamt of San Pedro
San Pedro 连接字符串
using System;namespace StringApplication
{class StringProg{static void Main(string[] args){string[] starray new string[]{Down the way nights are dark,And the sun shines daily on the mountain top,I took a trip on a sailing ship,And when I reached Jamaica,I made a stop};string str String.Join(\n, starray);Console.WriteLine(str);Console.ReadKey() ;}}
} 当上面的代码被编译和执行时它会产生下列结果
Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop
C# string.Format格式化日期
DateTime dt new DateTime(2017,4,1,13,16,32,108);
string.Format({0:y yy yyy yyyy},dt); //17 17 2017 2017
string.Format({0:M MM MMM MMMM}, dt);//4 04 四月 四月
string.Format({0:d dd ddd dddd}, dt);//1 01 周六 星期六
string.Format({0:t tt}, dt);//下 下午
string.Format({0:H HH}, dt);//13 13
string.Format({0:h hh}, dt);//1 01
string.Format({0:m mm}, dt);//16 16
string.Format({0:s ss}, dt);//32 32
string.Format({0:F FF FFF FFFF FFFFF FFFFFF FFFFFFF}, dt);//1 1 108 108 108 108 108
string.Format({0:f ff fff ffff fffff ffffff fffffff}, dt);//1 10 108 1080 10800 108000 1080000
string.Format({0:z zz zzz}, dt);//8 08 08:00string.Format({0:yyyy/MM/dd HH:mm:ss.fff},dt); //2017/04/01 13:16:32.108
string.Format({0:yyyy/MM/dd dddd}, dt); //2017/04/01 星期六
string.Format({0:yyyy/MM/dd dddd tt hh:mm}, dt); //2017/04/01 星期六 下午 01:16
string.Format({0:yyyyMMdd}, dt); //20170401
string.Format({0:yyyy-MM-dd HH:mm:ss.fff}, dt); //2017-04-01 13:16:32.108 除去string.Format()可以对日期进行格式化之外*.ToString()也可以实现相同的效果
DateTime dt new DateTime(2017,4,1,13,16,32,108);
dt.ToString(y yy yyy yyyy);//17 17 2017 2017
dt.ToString(M MM MMM MMMM);//4 04 四月 四月
dt.ToString(d dd ddd dddd);//1 01 周六 星期六
dt.ToString(t tt);//下 下午
dt.ToString(H HH);//13 13
dt.ToString(h hh);//1 01
dt.ToString(m mm);//16 16
dt.ToString(s ss);//32 32
dt.ToString(F FF FFF FFFF FFFFF FFFFFF FFFFFFF);//1 1 108 108 108 108 108
dt.ToString(f ff fff ffff fffff ffffff fffffff);//1 10 108 1080 10800 108000 1080000
dt.ToString(z zz zzz);//8 08 08:00dt.ToString(yyyy/MM/dd HH:mm:ss.fff); //2017/04/01 13:16:32.108
dt.ToString(yyyy/MM/dd dddd); //2017/04/01 星期六
dt.ToString(yyyy/MM/dd dddd tt hh:mm); //2017/04/01 星期六 下午 01:16
dt.ToString(yyyyMMdd); //20170401
dt.ToString(yyyy-MM-dd HH:mm:ss.fff); //2017-04-01 13:16:32.108
C#结构体
在 C# 中结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
结构体是用来代表一个记录。假设您想跟踪图书馆中书的动态。您可能想跟踪每本书的以下属性
TitleAuthorSubjectBook ID
定义结构体
为了定义一个结构体您必须使用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。
例如您可以按照如下的方式声明 Book 结构
struct Books
{public string title;public string author;public string subject;public int book_id;
}; 下面的程序演示了结构的用法
using System;
using System.Text;
namespace day01
{struct Books{public string title;public string author;public string subject;public int book_id;};class Program{static void Main(string[] args){Books Book1;Book1.title C programming;Book1.author Nuha Ali;Book1.subject C programming Tutorial;Book1.book_id 12345;Console.WriteLine(Book1 title:{0}, Book1.title);Console.WriteLine(Book1 author:{0}, Book1.author);Console.WriteLine(Book1 subject:{0}, Book1.subject);Console.WriteLine(Book1 book_id:{0}, Book1.book_id);Console.ReadKey();}}
}
运行结果: C#结构的特点
您已经用了一个简单的名为 Books 的结构。在 C# 中的结构与传统的 C 或 C 中的结构不同。C# 中的结构有以下特点:
结构可带有方法、字段、索引、属性、运算符方法和事件。结构可定义构造函数但不能定义析构函数。但是您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的且不能被改变。与类不同结构不能继承其他的结构或类。结构不能作为其他结构或类的基础结构。结构可实现一个或多个接口。结构成员不能指定为 abstract、virtual 或 protected。当您使用 New 操作符创建一个结构对象时会调用适当的构造函数来创建结构。与类不同结构可以不使用 New 操作符即可被实例化。如果不使用 New 操作符只有在所有的字段都被初始化之后字段才被赋值对象才被使用。
类 VS 结构
类和结构有以下几个基本的不同点
类是引用类型结构是值类型。结构不支持继承。结构不能声明默认的构造函数。
针对上述讨论让我们重写前面的实例
using System;
using System.Text;
namespace day01
{struct Books{private string title;private string author;private string subject;private int book_id;public void setValues(string t,string a,string s,int id){title t;author a;subject s;book_id id;}public void display(){Console.WriteLine(Title:{0}, title);Console.WriteLine(Author:{0}, author);Console.WriteLine(Subject:{0}, subject);Console.WriteLine(Book_id:{0}, book_id);}};class Program{static void Main(string[] args){Books Book1 new Books();Book1.setValues(C programming, qk, C programming Tutorial, 12345);Book1.display();Console.ReadKey();}}
}当上面的代码被编译和执行时它会产生下列结果 补充类与结构体的区别
1、结构体中声明的字段无法赋予初值类可以:
struct test001
{private int aa 1;
} 执行以上代码将出现“结构中不能实例属性或字段初始值设定”的报错而类中无此限制代码如下
class test002
{private int aa 1;
} 2、结构体的构造函数中必须为结构体所有字段赋值类的构造函数无此限制:
补充类与结构的选择
首先明确类的对象是存储在堆空间中结构存储在栈中。堆空间大但访问速度较慢栈空间小访问速度相对更快。故而当我们描述一个轻量级对象的时候结构可提高效率成本更低。当然这也得从需求出发假如我们在传值的时候希望传递的是对象的引用地址而不是对象的拷贝就应该使用类了。
结构和类的区别
结构是值类型它在栈中分配空间而类是引用类型它在堆中分配空间栈中保存的只是引用。结构类型直接存储成员数据让其他类的数据位于堆中位于栈中的变量保存的是指向堆中数据对象的引用。
C# 中的简单类型如int、double、bool等都是结构类型。如果需要的话甚至可以使用结构类型结合运算符运算重载再为 C# 语言创建出一种新的值类型来。
由于结构是值类型并且直接存储数据因此在一个对象的主要成员为数据且数据量不大的情况下使用结构会带来更好的性能。
因为结构是值类型因此在为结构分配内存或者当结构超出了作用域被删除时性能会非常好因为他们将内联或者保存在堆栈中。当把一个结构类型的变量赋值给另一个结构时对性能的影响取决于结构的大小如果结构的数据成员非常多而且复杂就会造成损失接下来使用一段代码来说明这个问题。
结构和类的适用场合分析
当堆栈的空间很有限且有大量的逻辑对象时创建类要比创建结构好一些对于点、矩形和颜色这样的轻量对象假如要声明一个含有许多个颜色对象的数组则CLR需要为每个对象分配内存在这种情况下使用结构的成本较低在表现抽象和多级别的对象层次时类是最好的选择因为结构不支持继承。大多数情况下目标类型只是含有一些数据或者以数据为主
C#枚举
枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。
C# 枚举是值类型。换句话说枚举包含自己的值且不能继承或传递继承
声明enum变量
声明枚举的一般语法:
enum enum_name
{ enumeration list
};
其中
enum_name指定枚举的类型名称enumeration list是一个用逗号分隔的标识符列表。
枚举列表中的每个符号代表一个整数值一个比它前面的符号大的整数值默认情况下第一个枚举符号的值是0例如:
enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
实例:
using System;namespace day01
{class Program{enum Day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};static void Main(string[] args){int x (int)Day.Sun;int y (int)Day.Fri;Console.WriteLine(Sun{0}\nFri{1},x,y);}}
}
当上面的代码被编译和执行时它会产生下列结果