开发工具与关键技术:Microsoft Visual Studio 2015、.NET
撰写时间:2019年07月22日
手工内存管理需要开发者管理内存块的分配和重新分配。手工管理内存既耗时又困难。提供自动内存管理可以使开发者从繁重的任务中解放出来。
在大多数情况下,自动内存管理可以在没有反面影响表现和性能的情况下增加代码的质量,提高开发者生产力。
例子:
public class Stack
{
private Node first = null;
public bool Empty
{
get {
return (first == null);
}
}
public object Pop()
{
if (first == null)
throw new Exception("Can't Pop from an empty Stack.");
else
{
object temp = first.Value;
first = first.Next;
return temp;
}
}
public void Push(object o)
{
first = new Node(o, first);
}
class Node
{
public Node Next;
public object Value;
public Node(object value) : this(value, null) { }
public Node(object value, Node next)
{
Next = next;
Value = value;
}
}
}
介绍了一个作为Node实例链接表执行类 Stack。Node实例在 Push方法中创建,当不再需要时被碎片收集。当其它程序没有任何可能去访问 Node实例时,它就符合碎片收集的条件了。例如当一个项目被从 Stack中移走,相关的 Node实例就变为符合碎片收集的条件。
例子:
class Test
{
static void Main()
{
Stack s = new Stack();
for (int i = 0; i < 10; i++)
s.Push(i);
s = null;
}
}
介绍了一个使用 Stack类的测试程序。Stack被创建并且初始化为包含 10个元素,然后被赋值为数据 null。一旦变量 s被赋值为 null后,Stack和相应的 10个 Node实例就变成符合碎片收集的条件了。碎片 收集程序马上就被允许进行清理,虽然还不需要这样做。
对于一个通常是使用自动内存管理,但有时需要精细控制或希望有些许性能提高的程序员来说,C#提供了编写“非安全”代码的能力。
这样的代码可以由指针类型直接处理,而且 fix对像可以暂时保护这些代码,防止被碎片收集程序收集。
从开发者和用户角度来看,这个“非安全”代码属性实际上是“安全”属性。
非安全代码必须用 unsafe修饰符明确标明,这样开发者就不会在偶然的情况下使用这项非安全属性,并且编译器和执行程序一起来保证非安全代码不会伪装为安全代码。
例子:
class Test
{
unsafe static void WriteLocations(byte[] arr)
{
fixed (byte* p_arr = arr)
{
byte* p_elem = p_arr;
for (int i = 0; i < arr.Length; i++) {
byte value = *p_elem;
string addr = int.Format((int)p_elem, "X");
Console.WriteLine("arr[{0}] at 0x{1} is {2}", i, addr, value);
p_elem++;
}
}
}
static void Main() {
byte[] arr = new byte[] { 1, 2, 3, 4, 5 };
WriteLocations(arr);
}
}
介绍了名为 WriteLocations的非安全方法,它选定一个数组实例并且用指针反复对元素进行操作。每个数组元素的标号,数据和位置写到控制台。这个程序的一个可能的输出为:
arr[0] at 0x8E0360 is 1
arr[1] at 0x8E0361 is 2
arr[2] at 0x8E0362 is 3
arr[3] at 0x8E0363 is 4
arr[4] at 0x8E0364 is 5
但是,准确的存储位置肯定要发生变化。