c#入门经典(3)(203)

特性

1
2
3
4
5
[DebuggerStepThrough]//调试跳过下面方法
public void DullMethod() {...}
[DoesInterestingThings(1000, WhatDoesItDo = "voodoo")]
public class DecoratedClass {}

动态类型

1
2
3
4
5
6
7
8
9
public static T Sum<T>(params T[] Args)
{
T sum = Args[0];
for (int i = 1; i < Args.Length; ++i)
{
sum += Args[i];
}
return sum;
}//上面这一段代码并不会编译通过

在C++中这是最最基本的函数模板,但是在C#中代码通不过,
因为泛型不是模板,它不会生成多份代码,T是当做object来处理的,
因此不能用来进行加法运算。

##所以c#又引入了动态类型的概念##
便可以如下:

1
2
3
4
5
6
7
8
9
public static T Sum<T>(params T[] Args)
{
dynamic sum = Args[0];
for (int i = 1; i < Args.Length; ++i)
{
sum += Args[i];
}
return sum;
}

C#编译器允许你通过dynamic对象调用任何方法,即使这个方法根本不存在,
编译器也不会在编译的时候报编译错误。只有在运行的时候,
它才会检查这个对象的实际类型

再看一段代码:

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
public class Duck
{
public string QQ()
{
Console.WriteLine("qq");
return "qq";
}
}
public class Humen
{
public string GG()
{
Console.WriteLine("gg");
return "gg";
}
}
class Program
{
public static string DoQG(dynamic dy)
{
string result = dy.GG();//由于是dynamic,所以任何代码都是对的,编译器更不会报错
return result ?? "hehe";//但是执行的话,由于duck类是没有GG这个函数的。会直接抛出异常。
}
static void Main(string[] args)
{
Duck duck = new Duck();
Humen hu = new Humen();
Console.WriteLine(DoQG(hu));
Console.WriteLine(DoQG(duck));
Console.ReadKey();
}
}

LINQ(Language Integrated Query)

它使得查询语句可以像数据库那样执行

1
2
3
4
int[] scores = new int[] { 97, 92, 81, 60 };
IEnumerable<int> sc = from score in scores where
score > 80 select score;
//如果自定义类型要如此的话,必须重写IEnumerable<T>接口

太多了,先跳过吧!

释放非托管的资源

c#的析构函数使用较少,释放的时机和位置由于不确定。
官方建议用IDisposable接口来代替析构函数(用于准确释放资源):

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
class Myclass : IDisposable
{
public void Dispose() {}//
}
//其用法有俩种
Myclass dd = null;
try
{
dd = new Myclass();
...
//do something
}
finally
{
if (dd)
dd.Dispose();
}
//以上做法保证了无论执行是否成功或异常,都要赶紧释放资源。唯一的确定就是写法太繁杂
using (Myclass dd = new Myclass())
{
...
//do something
}//如此写法就可以到相同效果


再说明下:
托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象;
非托管资源:不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象、gdi对象等;

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class SampleClass : IDisposable
{
//演示创建一个非托管资源
private IntPtr nativeResource = Marshal.AllocHGlobal(100);
//演示创建一个托管资源
private AnotherResource managedResource = new AnotherResource();
private bool disposed = false;
/// <summary>
/// 实现IDisposable中的Dispose方法
/// </summary>
public void Dispose()
{
//必须为true
Dispose(true);
//通知垃圾回收机制不再调用终结器(析构器)
GC.SuppressFinalize(this);
}
/// <summary>
/// 不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如C++)的规范
/// </summary>
public void Close()
{
Dispose();
}
/// <summary>
/// 必须,以备程序员忘记了显式调用Dispose方法
/// </summary>
~SampleClass()
{
//必须为false
Dispose(false);
}
/// <summary>
/// 非密封类修饰用protected virtual
/// 密封类修饰用private
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
// 清理托管资源
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// 清理非托管资源
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
//让类型知道自己已经被释放
disposed = true;
}
public void SamplePublicMethod()
{
if (disposed)
{
throw new ObjectDisposedException("SampleClass", "SampleClass is disposed");
}
//省略
}
}

重写Dispose接口为了及时释放非托管资源。
编写析构函数为了确保CLR的自动释放。

// //