- C#的变量命名规则
变量的名以字母、下划线或@开头,后面可以跟字母、数字、下划线,而不能包含空格、标点符号、运算符等其它符号。
变量名不能与C#中的关键字名称相同。这些关键字我们在附录A中给出。
变量名不能与C#中的库函数名称相同
对大小写敏感
同一变量名不允许重复定义
int @_a = 10;//正确
int @xy = 10;//正确
int _xy = 20;//正确
int @123 = 30;//错误
int @_123 = 60;//正确
1
2
3
4
5 - C#的数据类型
C#的基础数据类型并没有内置于C#语言中,而是内置于.net Framework中。
如,在c#中声明一个int类型的数据时,声明的实际上是.net结构System.Int32的一个实例。这听起来似乎很深奥,但其意义深远:这表示在语法上,可以把所有的基础数据类型看作是支持某些方法的类。类型实际上仍存储为基本类型。基本类型在概念上用.Net结构表示,所以肯定没有性能损失。
类型 描述 默认值
bool 布尔值 False
byte 8位无符号正数 0
char 16位字符 ‘\0’
short 16位有符号整型 0
int 32位整型有符号 0
float 32位单精度 0.0F
long 64位整形有符号 0L
double 64位双精度浮点型 0D
sbyte 8位有符号 0
short 16位有符号 0
unit 32位无符号 0
ushort 16位无符号 0
ulong 64位无符号 0
decimal 128位精度十进制 0.0M
sizeof关键字
sizeof([数据类型]) : 返回类型的字节数
- C#的值传递和引用传递
out修饰入参
被out修饰的参数在方法中要是用的话必须先初始化再使用.
ref修饰入参
被ref修饰的相当于C语言的指针.
方法调用传递实参的时候必须使用ref和out修饰.
static void ex1(ref int a, out int b)
{
b = a*10;
a = 10 + a;
}
public static void Main(string[] args)
{
int a = 10, b = 0;
ex1(ref a, out b);//使用ref和out修饰
Console.WriteLine(a+","+b);//20,100
Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
4. C#的类型转换
4.1 强转
该转换方式主要用于数字类型之间的转换,从int类型向long,float,double,decimal 类型转换可以使用隐式转换,
但从long型到int 就需要使用显示转换,即使用该类型的转换方式否则产生编译错误。
该方式对于浮点数会无条件的舍去,会失去精确度
对于char类型的到int类型的转换,传回的值是ASCII码.
int i1 = 10;
long l1 = 1000;
float f1 = 1234567890.0F;
double d1 = 1234567890.0D;
Console.WriteLine((int)l1);//1000
Console.WriteLine((int)f1);//1234567936
Console.WriteLine((int)d1);//1234567890
1
2
3
4
5
6
7
8
4.2 int.Parse([string 变量名])
该方式是将数字内容的字符串转换为int类型,如果字符串的内容为Null ,则抛出ArgumentNullException异常;如果字符串内容不是数字,则抛出FormatException异常。使用该方法只能处理字符串的内容,而且转换后的字符串内容要在int类型的可表示范围之内.
string s1 = “100”;
Console.WriteLine(int.Parse(s1));//OK
string s2 = “100a”;
Console.WriteLine(int.Parse(s2));//转换失败报错
1
2
3
4
5
4.3 int.TryParse(string s, out int result)
该方式也是将数字内容的字符串转换为int类型,但是该方式有比int.Parse 优越的地方,就是它不会出现异常,最后一个参数result是输出值,如果转换成功则输出相应的值,转换失败则输出0。
string s2 = “1000a”;
int result;
Console.WriteLine(int.TryParse(s2, out result));//False
Console.WriteLine(result);//0
1
2
3
4
4.4 Convert对象
提供了ToXxx([被转换的数据])一系列静态方法.
-
集合
非泛型集合的类和接口位于System.Collections命名空间。
泛型集合的类和接口位于System.Collections.Generic命名空间。
非泛型集合接口 泛型集合接口 说明
ICollection ICollection 定义所有集合的大小(Count),枚举器(foreach)和同步(copyto)方法,继承自IEnumerable
IList IList 表示可按照索引单独访问的一组对象(像数组一样)
IDictionary IDictionary 表示键/值对的集合
IComparer IComparer 定义类型为比较两个对象而实现的方法
IEqualityComparer IEqualityComparer 定义方法以支持对象的相等比较
IEnumerable IEnumerable 公开枚举器。实现了该接口意味着允许foreach语句循环访问集合中的元素
IEnumerator IEnumerator 支持在泛型集合上进行简单迭代
5.1 ArrayList
/* ------- 测试ArrayList ------ */
public static void Main1(String[] agrs)
{
// 1. ArrayList
//可重复添加元素,先行表结构
ArrayList alist = new ArrayList();
alist.Add(“abc”);
alist.Add(“abc”);
alist.Add(1230);
//alist.RemoveAt(0);//删除索引为0的元素
//alist.Remove(1230);//删除指定对象元素
//alist.RemoveRange(0, 2);//删除[0,2)的元素
alist.Insert(0, 1000);//插入一个对象
ArrayList a = new ArrayList();
a.Add(000);
a.Add(111);
alist.Insert(0, a);//插入一个集合//判断是否包含指定元素
Console.WriteLine(“是否包含{0}元素:{1}”, 1230, alist.Contains(1230));//增强for循环遍历ArrayList集合
foreach (var item in alist)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
5.2 HashTable
public static void Main2(String[] agrs)
{
///无序,不能重复
Hashtable ht = new Hashtable();
ht.Add(“one”, 100000);
ht.Add(“two”, 12000);
Persons p = new Persons();
ht.Add(p, 13000);//判断是否包含某个 key
Console.WriteLine(“是否包含该 key:{0} ?:{1}”, “one”, ht.Contains(“one”));//添加重复的key对应的value
//ht.Add(“one”, “the new one value”);//会报错
ht[“one”] = “the new one value”;//这样才可以//ht.Remove(“one”);//清楚指定 key 的元素
//ht.Clear();//清空foreach (var key in ht.Keys)
{
Console.WriteLine(“key:{0},value:{1}”, key, ht[key]);
}Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
5.3 Dictionary
/* ------ 3. 测试 Dictionary ------ */
public static void Main3(String[] args)
{
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, “one”);
dict.Add(2, “two”);
dict.Add(3, “three”);
dict.Add(4, “four”);
dict.Add(5, “five”);
dict.Add(6, “six”);//遍历
foreach (var key in dict.Keys)
{
Console.WriteLine(“key:{0},value:{1}”, key, dict[key]);
}//第二种遍历方式
Console.WriteLine("***********************");
//类似Java的Map的EntrySet
foreach (KeyValuePair<int, string> item in dict)
{
Console.WriteLine(“key:{0},value:{1}”, item.Key, item.Value);
}Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 -
多态
6.1 new关键字
子类不想重写父类的方法的时候使用new关键字修饰方法.
在用作修饰符时,new关键字可以显式的隐藏从基类继承的成员。隐藏继承的成员时,该成员的派生版本将替换基类版本。虽然可以不使用new修饰符的情况下隐藏成员,但会生成警告。如果使用new显示隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。
class Person
{
string _name;
public string Name
{
set { this._name = value; }
get { return this._name; }
}
public Person(string name)
{
this._name = name;
}
public void say() {
Console.WriteLine("我是人类say2()");
}
}
class Chinese : Person
{
public Chinese(string name) : base(name) { }
//子类不想重写父类的该方法,即使用new关键字来隐藏父类的say方法
public new void say() {
Console.WriteLine("我是中国人say2(...)");
}
}
public static void Main(string[] args)
{
Person pc1 = new Chinese(“小明”);
pc1.say();//我是人类say2()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
6.2 virtual和override
只有被virtual,abstract,override修饰的方法可以被子类重写,达到多态的效果.
class Person
{
string _name;
public string Name
{
set { this._name = value; }
get { return this._name; }
}
public Person(string name)
{
this._name = name;
}
//父类的方法被 virtual 修饰
public virtual void say()
{
Console.WriteLine("我是人类,我叫:{0}",this.Name);
}
}
class Chinese : Person
{
public Chinese(string name) : base(name) { }
//子类重谢父类的 virtual 修饰的方法
public override void say()
{
Console.WriteLine("我是中国人,我叫:{0}", this.Name);
}
}
public static void Main(string[] args)
{
Person pc1 = new Chinese(“小明”);
pc1.say();//我是中国人,我叫:小明
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
6.3 abstract 修饰符
和Java中一样abstract修饰符修饰的为抽象类,和抽象方法.
//定义一个抽象类,抽象类不允许new出来和Java一样
public abstract class Animal
{
public Animal() { Console.WriteLine(“抽象类Animal的构造函数”); }
public abstract void Bark();//抽象方法不允许实现和Java一样
}
public class Cat : Animal
{
public override void Bark()
{
Console.WriteLine(“Cat 对抽象类 Animal 的实现!”);
}
}
//虽然抽象类不能直接new但是和Java一样在子类初始化的时候仍然后初始化抽象类
Animal cat = new Cat();
cat.Bark();//Cat 对抽象类 Animal 的实现!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
7. IO操作
using System.IO;
7.1 File 类
读取所有的字节返回一个字节数组
File.ReadAllBytes(@“E:\test.txt”);
// 1. 读取所有的字节返回一个字节数组
byte[] buff = File.ReadAllBytes(@“E:\test.txt”);
string res = Encoding.Default.GetString(buff);
Console.WriteLine(res);
1
2
3
4
写入字节数组到指定路径
File.WriteAllBytes(@“E:\test1.txt”,buff);
// 1.2 写入字节数组到指定路径
File.WriteAllBytes(@“E:\test1.txt”,buff);
1
2
读取所有的行,指定编码格式为默认ansc
string[] lines = File.ReadAllLines(@“E:\test.txt”,Encoding.Default);
//2.读取所有的行,指定编码格式为默认aisn
string[] lines = File.ReadAllLines(@“E:\test.txt”,Encoding.Default);
Console.WriteLine(lines[0]);
1
2
3
读取整个文档的文本内容
string content = File.ReadAllText(@“E:\test.txt”, Encoding.Default);
// 3.读取整个文档的文本内容
string content = File.ReadAllText(@“E:\test.txt”, Encoding.Default);
1
2
7.2 FileStream 字节读写类
FileStream(@“E:\test.txt”,FileMode.OpenOrCreate,FileAccess.Read);:读方式
Read(buff, 0, buff.Length): 从流中读取字到byte数组
FileStream(@“E:\test3.txt”, FileMode.OpenOrCreate, FileAccess.Write);:写方式
Write(buff, 0, len) :写入byte数组内容到流
/* ------- 2. FileStream ------- */
public static void Main2(String[] args)
{
//文件路径,打开方式,文件操作方式
FileStream fsRead = new FileStream(@“E:\test.txt”,FileMode.OpenOrCreate,FileAccess.Read);
FileStream fsWrite = new FileStream(@“E:\test3.txt”, FileMode.OpenOrCreate, FileAccess.Write);
byte[] buff = new byte[1024];
int len = 0;
while ((len = fsRead.Read(buff, 0, buff.Length)) != 0)
{
string str = Encoding.Default.GetString(buff, 0, len);
Console.WriteLine(str);
fsWrite.Write(buff, 0, len);
}
Console.WriteLine(“OK”);
//关闭流
fsRead.Close();
fsWrite.Close();
//释放资源
fsRead.Dispose();
fsWrite.Dispose();
Console.ReadKey();
}
//测试自定义的方法
public static void Main3(string[] args)
{
copyFile(@“E:\test3.txt”,@“E:\text4.txt”);
}
//使用 FileStream 封装复制文件的方法
public static void copyFile(string source,string target)
{
//使用 using 来管理文件流的关闭和释放
using (FileStream fsRead = new FileStream(source, FileMode.OpenOrCreate, FileAccess.Read))
{
using (FileStream fsWrite = new FileStream(target, FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] buff = new byte[1024];
int len = 0;
while ((len = fsRead.Read(buff, 0, buff.Length)) != 0)
{
fsWrite.Write(buff, 0, len);
}
Console.WriteLine(“OK”);
}
}
}// end of copyFile()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
7.3 StreamReader 字符读写类
StreamReader(@“E:\text4.txt”, Encoding.Default)读,指定编码格式
EndOfStream : 判断是否到达流的结尾
ReadLine() : 读取一行
StreamWriter(@“E:\test5.txt”,true)写,第二个参数是否追加
WriteLine(str) : 写入一行
/* -------- 3. StreamReader 字符读写------------ */
public static void Main4(String[] args)
{
using(StreamReader sr = new StreamReader(@“E:\text4.txt”, Encoding.Default))
{
using (StreamWriter sw = new StreamWriter(@“E:\test5.txt”,true))
{
//如果没到流的结尾
while (!sr.EndOfStream)
{
string str = sr.ReadLine();
Console.WriteLine(str);
sw.WriteLine(str);
}
}
}
Console.WriteLine(“OK”);
Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
8. 访问修饰符
public : 公开的公共的
private : 私有的只能在当前类的内部访问的
protected : 受保护的,只能在当前类的内部以及该类的子类中访问
internal : 只能在当前的项目中访问,在同一个项目中,internal和public的权限是一样的
protected internal : protected + internal
能修饰类的访问权限只有两个:public,internal
可访问性不一致问题:子类的访问权限不能高于父类的访问权限,会暴父类的成员
9. 序列化和反序列化
类似Java中的序列化.
- BinaryFormatter bf = new BinaryFormatter();:创建序列化对象
- bf.Serialize(fw, man);//第一个是输出流,第二个是被序列化的对象
- BinaryFormatter bf = new BinaryFormatter();:创建反序列化对象
- Man man2 = (Man)bf.Deserialize(fr);//fr为序列化的文件输出流
[Serializable]//标志位表示该类可被序列化
public class Man
{
public string Name { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
}
static void Main(string[] args)
{
Man man = new Man();
man.Name = “张三”;
man.Age = 15;
man.Gender = “男”;
//创建输出流
using (FileStream fw = new FileStream(@"E:\\ManObj.txt",FileMode.OpenOrCreate,FileAccess.Write))
{
//创建序列化对象
BinaryFormatter bf = new BinaryFormatter();
//开始序列化
bf.Serialize(fw, man);//第一个是输出流,第二个是被序列化的对象
}
Console.WriteLine("序列化OK");
//反序列化,先创建输入流
using (FileStream fr = new FileStream(@"E:\\ManObj.txt",FileMode.Open,FileAccess.Read))
{
//创建序列化对象
BinaryFormatter bf = new BinaryFormatter();
//开始反序列化
Man man2 = (Man)bf.Deserialize(fr);
Console.WriteLine(man2.Name);
Console.WriteLine(man2.Age);
Console.WriteLine(man2.Gender);
}
Console.WriteLine("反序列化OK");
Console.ReadKey();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
10. 密封类partial
密封类,可以继承其他类,但是无法被其他类继承
//被 partial 修饰的类表示部分类
partial class Person
{
private string _name = “bart”;
}
partial class Person
{
void say()
{
//相当于同一个类,可以使用上面一个部分类的成员
Console.WriteLine(“部分类调用自己的成员:{0}”,_name);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
11. 接口
接口的特点:
- 接口不允许使用任意修饰符默认就是 public
- 接口可以继承多个接口
- 接口可以有成员属性
- 子类继承的父类和接口中的方法重名的时候显示使用接口的方法,并重写IFlayable.say(){XXXX;}
namespace _08接口特点
{
class Program
{
///
/// 接口的特点:
/// 1. 接口不允许使用任意修饰符默认就是 public
/// 2. 接口可以继承多个接口
/// 3. 接口可以有成员属性
/// 4. 子类继承的父类和接口中的方法重名的时候显示使用接口的方法,并重写
/// IFlayable.say(){XXXX;}
///
///
static void Main(string[] args)
{
IFlyable ifa = new SuperMane();
ifa.Fly();
Bird b = new SuperMane();
b.Fly();
Console.ReadKey();
}
}
//继承类同时实现接口
public class SuperMane : Bird ,IFlyable
{
new public void Fly()
{
Console.WriteLine("我是超人,我会飞,来自父类");
}
//显示实现接口的同名方法
void IFlyable.Fly()
{
Console.WriteLine("我是超人,我会飞,来自接口");
}
}
public class Bird
{
public void Fly()
{
Console.WriteLine("我是鸟,我会飞!");
}
}
//默认是public修饰,I开头able结尾
public interface IFlyable
{
//接口的方法不能被 public 修饰,因为它本身就默认是 public 的
void Fly();
//不允许有方法体的方法
//string Name { get; set; }
}
}