一个例子
using System;
namespace Test {
public class HelloWorld {
public static void Main() {
Console.WriteLine("hello world!");
return;
}
}
}
// Main函数返回值类型为void或者int
// Main函数也可带参数,形式为Main(String[] args)
基本数据类型
值类型,引用类型
值类型存储在栈上,引用类型存储在堆上
预定义类型
- 整型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
sbyte | System.SByte | 8位有符号的整数 | -128~127 |
short | System.Int16 | 16位有符号的整数 | -32768~32767 |
int | System.Int32 | 32位有符号的整数 | |
long | System.Int64 | 64位有符号的整数 | |
byte | System.Byte | 8位无符号的整数 | |
ushort | System.UInt16 | 16位无符号的整数 | |
uint | System.UInt32 | 32位无符号的整数 | |
ulong | System.Uint64 | 64位无符号的整数 |
- 浮点类型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
float | System.Single | 32位单精度浮点数 | |
double | System.Double | 64位双精度浮点数 |
- decimal类型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
decimal | System.Decimal | 128位高精度十进制数表示法 |
- bool类型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
bool | System.Boolean | 表示true或者false |
- 字符类型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
char | System.Char | 表示一个16位的unicode字符 |
- 预定义的引用类型
名称 | 对应.NET内置类型 | 说明 | 范围 |
---|---|---|---|
object | System.Object | 根类型 | |
string | System.String | Unicode字符串 |
运算符
-算数运算符
加号(+),减号(-),乘号(*),除号(/),取模(%)
-赋值运算符
=
-自动递增递减
递增(++),递减(–)
-关系运算符
大于(>),小于(<),大于等于(>=),小于等于(<=),等于(==),不等于(!=)。等于和不等于适用于所有内建的数据类型,但其他比较不适用于boolean 类型
-逻辑运算符
AND(&&),OR(||),NOT(!),只可将AND,OR 或NOT 应用于布尔值。与在C 及C++中不同,不可将一个非布尔值当作布尔值在逻辑表达式中使用。”短路”,一旦逻辑运算表达式的值已经求出,后续表达式不计算值。
-按位运算符
若两个输入位都是1,则按位AND运算符(&)在输出位里生成一个1;否则生成0。
若两个输入位里至少有一个是1,则按位OR 运算符(|)在输出位里生成一个1;只有在两个输入位都是0的情况下,它才会生成一个0。
若两个输入位的某一个是1,但不全都是1,那么按位XOR(^,异或)在输出位里生成一个1。
按位NOT(~,也叫作“非”运算符)属于一元运算符;它只对一个自变量进行操作(其他所有运算符都是二元运算符)。按位NOT生成与输入位的相反的值——若输入0,则输出1;输入1,则输出0。
按位运算符可与等号(=)联合使用,以便合并运算及赋值:&=,|=和^=都是合法的(由于~是一元运算符,所以不可与=联合使用)。
-移位运算符
移位运算符面向的运算对象也是二进制的“位”。可单独用它们处理整数类型(主类型的一种)。
左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。
-三元if-else运算符
布尔表达式 ? 值0:值1
-字符串运算符+
如果想通过“加号”连接字串(使用Java 的早期版本),请务必保证第一个元素是字串(或加上引号的一系列字符,编译能将其识别成一个字串)。
-造型运算符
void casts() {
int i = 200;
long l = (long)i;
long l2 = (long)200;
}
-类型信息运算符
sizeof, is, typeof, as
控制流
-i f- e l s e
int result = 0;
if(testval > target)
result = -1;
else if(testval < target)
result = +1;
else
result = 0; // match
return result;
-while
while(布尔表达式)
语句
-do while
do
语句
while(布尔表达式)
-for
for( char c = 0; c < 128; c++) {
if (c != 26 ) // ANSI Clear screen
Console.WriteLine("value: " + (int)c +" character: " + c);
}
对于集合
List list = new ArrayList();
list.add(3);
list.add(2);
list.add(10);
list.add(4);
list.add(70);
foreach(int attribute in list) {
Console.WriteLine(attribute);
}
-break,continue
break 用于强行退出循环,不执行循环中剩余的语句。而continue 则停止执行当前的反复,然后退回循环起始和,开始新的反复。
-switch
switch(整数选择因子) {
case 整数值1 : 语句; break;
case 整数值2 : 语句; break;
case 整数值3 : 语句; break;
case 整数值4 : 语句; break;
case 整数值5 : 语句; break;
//..
default:语句;
}
名字空间
//定义名字空间
namespace XXX {
}
//使用名字空间
using XXX;
// 名字空间别名
using alias = NamespaceName; //格式
引用空间对象 alias::classA,注意‘::‘操作符
数组
int[] myArray;
int[] myArray = new int[4];
int[] myArray = new int[] {1,2,3,4};
int[] myArray = new int[4] {1,2,3,4};
int[] myArray = {1,2,3,4};
访问数组,myArray[0], 数组长度 myArray.Length
引用类型数组
Person[] myPersons = new Person[2];
myPersons[0] = new Person();
myPersons[1] = new Person();
多维数组
int[,] twoDim = {
{1,2,3},
{4,5,6},
{7,8,9}
}
访问 twoDim[1,2]
锯齿数组
int[][] myArray = new int[3][];
myArray[0] = new int[2] {1,2};
myArray[1] = new int[4] {1,2,3,4};
myArray[2] = new int[3] {1,2,3};
枚举
public enum TimeOfDay {
Morning = 0,
Afternoon = 1,
Evening = 2
}
TimeOfDay.Morning //使用方式,不同于c++
类型转换,装箱拆箱
预处理命令
#define DEBUG
#undef DEBUG
#if XXX
#elif XXX
#endif
#if XXX
#else
#endif
#if XXX
#endif
warning和error宏,编译器编译遇到时会提示后面跟的字符串,分别产生警告或错误。
#warning "..........."
#error ".............."
region用于把代码标记为有给定名的一个块
#region XXX
#endregion
#line指令可以用于改变编译器在警告和错误信息中显示的文件名和行号信息
#pragma可以抑制或者还原编译警告
#pragma warning disable 169
XXXX
#pragma warning restore 169
命名风格
名称依据功能命名而不是类型。
不要采用下划线形式命名。
名称空间和类,以及类的方法的属性才有Pascal大小写形式,即EmployeeSalary,单词首字母大写
私有变量,函数参数才有camel大小写形式,即employeeSalary,首单词首字母小写,其余单词首字母大写。
属性
private int age;
public int Age {
get
{
return age;
}
set
{
age = value;
}
}
可以只设置一个方法,set或者get,表示为只读或者只写属性
也可以给set或者get方法加private属性
自动实现属性
public int Age {get;set;} //会自动实现后备变量
ref,out,参数默认值
// ref修饰参数传入前必须初始化,修改会被带出函数
int count = 0;
void func(ref i) {
....
}
func(ref count);
// out修饰参数必须在函数内被修改,修改会被带出函数
int count;
void func(out i) {
i++; // 修改参数
}
func(out count);
// 函数参数可以给默认值,但必须是在最后的参数
void func(int a, int b = 0) {
}
const,readonly
c#中const变量必须在定义时初始化,而且默认是static
readonly变量是具有只读属性,不默认static,可以不在定义时初始化,但必须在构造函数中初始化,可以作为类实例只读变量,不同的类实例有不同的值,但后续只读
函数,重载
函数可以重载参数
类
public class Customer :Person {
private int productId;
public void Buy() {
............
}
public void Pay() {
............
}
}
构造函数
public class A{
private int b;
public A() : this(10) { //调用其他构造函数
}
public A(int initValue) { //构造函数,初始化类成员
b = initValue;
}
public static int a;
static A() { //静态构造函数,只会调用一次,初始化类静态变量
}
}
this,base
this表示类本身,base表示基类
接口
public Interface IDisposable {
void Dispose();
}
public Interface2 : Interface1 {
}
结构(用struct定义)
结构是值类型,而不是引用类型
struct Dimensions {
public double Length;
public double Width;
}
不能继承一个结构
结构定义的构造函数必须有参数
结构都是继承自System.ValueType类
部分类
partial关键字允许把类、结构或接口放在多个文件中
partial class A{
public void Method1() {
}
}
partial class A {
public void Method2() {
}
}
所有的同一类的部分了必须采用一样的类修饰符(public等关键字)
静态类
static class A { // static修饰的类,无法实例化
}
修饰符
可见性修饰符
修饰符 | 应用于 | 说明 |
---|---|---|
public | 类型或成员 | 任何代码均可以访问该项 |
protected | 类型和内嵌类型的所有成员 | 只有派生的类型能够访问 |
internal | 类型或成员 | 只能在包含它的程序集中访问该项 |
private | 类型和内嵌类型的所有成员 | 只能在它所属类型中访问该项 |
protected internal | 类型和内嵌类型的所有成员 | 只能在包含它的程序集和派生类型的任何代码中访问该项 |
其他修饰符
修饰符 | 应用于 | 说明 |
---|---|---|
new | 函数成员 | 成员用相同的签名隐藏继承的成员 |
static | 所有成员 | 静态成员或者函数 |
virtual | 仅函数成员 | 虚函数 |
abstract | 仅函数成员 | 抽象函数 |
override | 仅函数成员 | 虚函数的子类实现 |
sealed | 类,方法,属性 | 对于类,不能被继承。对于属性和方法,成员已重写并继承的虚拟成员,任何派生类中不能重写该成员,该修饰符修饰属性和方法时必须和override一起使用 |
extern | 仅静态[DllImport]方法 | 成员在外部语言实现 |
virtual,abstract修饰的成员在派生类中实现都需要加override关键字
new是让基类看不到派生类中的方法,为非虚函数修饰;virtual、override是为了让基类看到派生类的实现
System.Object
所有对象都是继承自该类
相关成员函数参照:
https://msdn.microsoft.com/zh-cn/library/system.object(v=vs.80).aspx
扩展类的方法
如果没有类源码,但又想给类扩展方法,可以采用静态类来扩展类的方法。
public statio class MoneyExtension {
public static void AddToAmount(this Money money, decimal amountToAdd) {
money.Amount += amountToAdd;
}
} // 给Money类扩展AddToAmount方法
调用money.AddToAmount(amount);
继承
C#只能继承自一个类,可以继承多个接口,属于单一继承
public class A {
public A() { //构造函数
}
public virtual void func() { // 虚函数
}
}
public class B : A, Interface1, Interface2 {
public B() : base() { // 调用基类构造函数
}
public override void func() { // 虚函数
}
}
抽象类
public abstract class C { //抽象类
public abstract void func(); //抽象函数,不用实现
}
密封类
public sealed class D { //密封类,无法被继承
}
相等比较
用‘==’比较,值类型比较值,引用类型比较引用对象是否同一个
用 equals方法可以自己重写比较引用对象的值是否相等
委托和事件
delegate void func(); //定义委托
func func1 = new func(Function); //赋值委托
public event func FuncEvent; // 事件
FuncEvent += func1;
FuncEvent -= func2;
泛型
运算符重载
集合
反射
异常处理
try {
}
catch(Exception e) {
}
finally {
}