C#是一个彻底的、面向对象的语言,C语言是面向过程的,C++既可以面向过程也可以面向对象。在实际编程中,C#都是在命名空间中定义类,然后在类内编写程序的入口函数Main
C#使用垃圾回收机制,这和C/C++动态分配内存具有巨大的差异。在C/C++中需要malloc/new来创建动态内存,并且还需要用户来释放创建的内存free/delete;在C#中用户创建内存后由系统来释放。
C#中的数据类型和C/C++有许多不同。在C#中数据类型分为2大类,值类型和引用类型,值类型可以直接进行赋值,而引用类型需要使用new先创建空间(托管堆区)然后返回这个空间的索引赋值给变量;值类型的储存空间和引用类型的索引在同一储存空间,但和引用类型new的空间不在同一区。
浮点型:
C#增添了decimal类型,是128位的数据类型,比double、float精度更高。
布尔型:
C#中bool无法和int相互转换,(在C中没有bool类型),C++中的bool类型可以和int相互转换,都是占1字节空间。
整型:
C#中增添了cbyte类型的整数,占1字节
字符编码:
C#采用16位的Unicode编码,占2字节;C/C++中字符采用ASIC编码,占用1字节。
结构类型:
在C#中,定义struct结构体,不允许在结构体里给变量赋值,只有静态变量才能赋值,并且构造函数的定义必须带参数;在C/C++中,定义struct结构体,允许在结构体里给变量赋值,允许构造函数不带参数。
const关键字
使用const修饰符进行声明时,用户定义的类型(包括类、结构、数组)不能为const,不能在表达式的作为左值出现。
var关键字
在C#3.0开始新增的特性,使用关键字var,定义推断类型,没有auto关键字;在C++中,使用auto关键字,声明推断类型。auto和var区别在于,var变量只能定义在函数内部作为局部变量,而auto则没有这个限制。
在C#中,数学函数定义在名字空间System中的Math类里,使用时需要在全局using System,然后Math.函数,例如(double b = Math.Sqrt(10));在C/C++中,数学函数定义在math头文件中,使用的时候直接include头文件,然后直接调用相应的函数。
//Convert.ToInt32(String)用法:将Int32范围内的整数字符串转换为对应的整数,例如下面的values只有"-18"、" 0", "137"、Int32.MaxValue.ToString()可以使用该函数转换对应的整数。
string[] values = { "One", "1.34e28", "-26.87", "-18", "-6.00",
" 0", "137", "1601.9", Int32.MaxValue.ToString() };
int result;
foreach (string value in values)
{
try
{
result = Convert.ToInt32(value);
Console.WriteLine("Converted the {0} value '{1}' to the {2} value {3}.",
value.GetType().Name, value, result.GetType().Name, result);
}
catch (OverflowException)
{
Console.WriteLine("{0} is outside the range of the Int32 type.", value);
}
catch (FormatException)
{
Console.WriteLine("The {0} value '{1}' is not in a recognizable format.",
value.GetType().Name, value);
}
}
类修饰符 class 类名{
成员修饰符 数据类型 标识符;
成员修饰符 返回值类型 方法名(){}
}
类修饰符:
有多种类型(public、private、internal、protected等等),如果省略则默认为internal(表示只有同一文件中的类型才可以访问)
成员修饰符
有多种成员修饰符(public、private、internal、protected、protected internal等等),如果省略则默认为private(表示只有同一文件中的类型才可以访问)
1)在C#中,增添了访问成员变量的方法,可以使用set和get访问类中的字段,set块负责属性的写入工作,get块负责属性的读取工作
class Program
{
static void Main(string[] args)
{
Hero hero = new Hero();
hero.Life = 10; //属性写操作
int k = hero.Life; //属性读操作
Console.WriteLine(k);
Console.WriteLine(Hero.c);
}
}
class Hero
{
private int age; // 字段
/*
public int Life{set;get;}
等效于下面的属性
*/
public int Life
{
get
{
return life;
}
set
{
life = value;
}
} // 属性
public Hero(k) // 构造函数
{
age = k;
}
public int Next() // 方法
{
return age + 1;
}
}
2)静态变量和方法
using System;
namespace Myname
{
class Hello
{
static void Main()
{
SayHello_1();
SayHello_1(); //错误,在static函数内调用同类的成员函数,需要保证该函数也是static
}
static void SayHello_1()
{
Console.WriteLine("hello!");
}
static void SayHello_2()
{
Console.WriteLine("hello!");
}
}
}
1)读取字符:为输入缓冲区的第一个字符
2)输入缓冲区状态:读取字符后的所有字符,一般是回车。
3)回车的Int32值在C#中,与C/C++不同:在C#为13,在C/C++为10
官方参考文档
//使用方法1:
int x1 = Console.Read();
char ch = Convert.ToChar(x1);
Console.WriteLine(ch);
//使用方法2:
char x2 = (char)Console.Read();
Console.WriteLine(x2);
2)ReadLine
从标准输入流读取下一行字符,返回String类型。如果没有更多的可用行,则为 null
参考文档
因为数据分为值类型、引用类型。直接使用值类型作为实参传给值类型的形参,属于值传递,若想要将值类型作为引用传递,需要加 ref (或out) 关键字。引用类型作为实参传递给引用类型,也属于值传递,因为是句柄的拷贝,但是会改变实参指向的内容,若想要将引用类型作为引用传递,即不拷贝句柄,需要加 ref 关键字。
(ref修饰的实参需要给实参赋初值,而out不用)
using System;
namespace Myname
{
class Hello
{
static void Main()
{
int a = 10;
int b = 20;
Swap_1(a, b); //值传递
Swap_2(ref a, ref b); //引用传递
Console.WriteLine("{0} && {1}", a, b);
Console.ReadLine();
}
static void Swap_1(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
static void Swap_2(ref int a, ref int b)
{
int tmp = a;
a = b;
b = tmp;
}
}
}
在C#里允许跳过中间的默认参数,直接给后面的默认参数赋值(在C/C++中是不允许的),这样的调用参数成为命名参数。
static void Main()
{
Swap_2(4, 5, d:10); //这里直接跳过了第3个默认参数,而使用命名参数给第4个默认参数赋值,在C/C++中是不允许的
}
static void Swap_2(int a, int b, int c = 1, int d = 2)
{
int tmp = a;
a = b;
b = tmp;
}