银河

SKYIV STUDIO

  博客园 :: 首页 :: 博问 :: 闪存 :: :: :: 订阅 订阅 :: 管理 ::

System.IO.Stream 类的 Null 字段

我们知道,.NET Framework Base Class Library 中的 System.IO.Stream 类有一个静态字段 Null,如下所示:

public static readonly Stream Null;

MSDN 中是这么描述的:

无后备存储区的 Stream。使用 Null 将输出重定向到不占用任何操作系统资源的流。 当在 Null 上调用提供写入的 Stream 方法时,该调用只是返回,没有任何数据写入。 Null 还实现一个返回零而不读取数据的 Read 方法。

Microsft .NET Framework 4 中的相关代码

使用 .NET Reflector 查看 Microsoft .NET Framework 4 类库的相关代码,经整理后如下所示:

 1 namespace System.IO
2 {
3 [Serializable, ComVisible(true)]
4 public abstract class Stream : MarshalByRefObject, IDisposable
5 {
6 [Serializable]
7 private sealed class NullStream : Stream
8 {
9 internal NullStream() { }
10 protected override void Dispose(bool disposing) { }
11 public override void Flush() { }
12 public override int Read([In, Out] byte[] buffer, int offset, int count) { return 0; }
13 public override int ReadByte() { return -1; }
14 public override long Seek(long offset, SeekOrigin origin) { return 0L; }
15 public override void SetLength(long length) { }
16 public override void Write(byte[] buffer, int offset, int count) { }
17 public override void WriteByte(byte value) { }
18 public override bool CanRead { get { return true; } }
19 public override bool CanSeek { get { return true; } }
20 public override bool CanWrite { get { return true; } }
21 public override long Length { get { return 0L; } }
22 public override long Position { get { return 0L; } set { } }
23
24 [HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
25 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
26 {
27 if (!this.CanRead) __Error.ReadNotSupported();
28 return base.BlockingBeginRead(buffer, offset, count, callback, state);
29 }
30
31 [HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
32 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
33 {
34 if (!this.CanWrite) __Error.WriteNotSupported();
35 return base.BlockingBeginWrite(buffer, offset, count, callback, state);
36 }
37
38 public override int EndRead(IAsyncResult asyncResult)
39 {
40 if (asyncResult == null) throw new ArgumentNullException("asyncResult");
41 return Stream.BlockingEndRead(asyncResult);
42 }
43
44 public override void EndWrite(IAsyncResult asyncResult)
45 {
46 if (asyncResult == null) throw new ArgumentNullException("asyncResult");
47 Stream.BlockingEndWrite(asyncResult);
48 }
49 }
50
51 public static readonly Stream Null;
52 static Stream() { Null = new NullStream(); }
53 }
54 }

可以看出,Stream 类的 Null 字段虽然声明为 Steam 类型,但实际上初初始化为 NullStream 类型。而这个 NullStream 类是 Stream 类的内部 private 类,并且是 Stream 类的派生类。

实际上,上述源程序文件中第 24 到 48 行的四个 override 的用于异步读写的方法不是必需的,可以省略,因为基类提供的相应的 virtual 方法已经能够正确的工作了。

此外,第 27 行和第 34 行的 if 语句是完全没有必要的,看看第 18 行和第 20 行就会明白了。

Mono 2.10.9 中的相关代码

现在来看看 Mono 2.10.9 中的相关代码:

 1 // mono-2.10.9/mcs/class/corlib/System.IO/Stream.cs
2 namespace System.IO
3 {
4 [Serializable]
5 [ComVisible(true)]
6 public abstract class Stream : MarshalByRefObject, IDisposable
7 {
8 public static readonly Stream Null = new NullStream();
9 }
10
11 class NullStream : Stream
12 {
13 public override bool CanRead { get { return true; } }
14 public override bool CanSeek { get { return true; } }
15 public override bool CanWrite { get { return true; } }
16 public override long Length { get { return 0; } }
17 public override long Position { get { return 0; } set { } }
18 public override void Flush() { }
19 public override int Read(byte[] buffer, int offset, int count) { return 0; }
20 public override int ReadByte () { return -1; }
21 public override long Seek(long offset, SeekOrigin origin) { return 0; }
22 public override void SetLength(long value) { }
23 public override void Write(byte[] buffer, int offset, int count) { }
24 public override void WriteByte(byte value) { }
25 }
26 }

可以看出,在 Mono 中,NullStream 类不再是 Stream 类的内部类,而是 System.IO 命名空间中的 internal 类。当然,NullStream 仍然是 Stream 类的派生类。内部实现基本上和 Microsoft 的实现差不多,除了不再 override 四个用于异步读写的 virtual 方法。

不管是 Microsoft 的实现,还是 Mono 的版本,NullStream 类对外界都是不可见,只能通过 Stream.Null 字段访问,也只这唯一的实例。

测试程序

我们写一个测试程序吧:

 1 using System;
2 using System.IO;
3
4 static class Tester
5 {
6 static void Main()
7 {
8 Console.WriteLine("OS Version: " + Environment.OSVersion);
9 Console.WriteLine("CLR Version: " + Environment.Version);
10 Console.WriteLine("Stream.Null: " + Stream.Null);
11 }
12 }

在 openSUSE 12.1 操作系统中编译和运行:

ben@vbox:~/work> dmcs --version
Mono C# compiler version 2.10.9.0
ben@vbox:~/work> dmcs Tester.cs
ben@vbox:~/work> mono Tester.exe
OS  Version: Unix 3.1.9.1
CLR Version: 4.0.30319.1
Stream.Null: System.IO.NullStream

可以看出,在 Mono 中,NullStream 类位于 System.IO 命名空间。

在 Windows Vista 操作系统中编译和运行:

E:\work> csc Tester.cs
Microsoft(R) Visual C# 2010 编译器 4.0.30319.1 版
版权所有(C) Microsoft Corporation。保留所有权利。

E:\work> Tester
OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2
CLR Version: 4.0.30319.239
Stream.Null: System.IO.Stream+NullStream

上面的“+”号表示 NullStream 类是 System.IO.Stream 类的内部类。

在 Winows 7 操作系统中编译和运行:

C:\Work> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc Tester.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.

C:\Work> Tester
OS  Version: Microsoft Windows NT 6.1.7601 Service Pack 1
CLR Version: 4.0.30319.239
Stream.Null: System.IO.Stream+NullStream

在 Windows 8 Consumer Preview 操作系统中编译和运行:

C:\work> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc Tester.cs
Microsoft (R) Visual C# Compiler version 4.0.30319.17379
for Microsoft (R) .NET Framework 4.5
版权所有 (C) Microsoft Corporation。保留所有权利。

C:\work> Tester
OS  Version: Microsoft Windows NT 6.2.8250.0
CLR Version: 4.0.30319.17379
Stream.Null: System.IO.Stream+NullStream

Windows 8 已经预先安装了 .NET Framework 4.5 (100% 兼容 .NET Framework 4),但是没有预装 .NET Framework 2.0、3.0 和 3.5。

而 Window 7 操作系统刚好相反,预装了 .NET Framework 2.0、3.0 和 3.5,但没有预装 .NET Framework 4。

实际上,Windows 2000、Windows XP 和 Windows Server 2003 都是 Windows NT 5.x 内核的,而 Windows Vista、Windows 7 和 Windows 8 都是 Windows NT 6.x 内核的:

  • Windows 2000: Windows NT 5.0
  • Windows XP    : Windows NT 5.1
  • Windows 2003: Windows NT 5.2
  • Windows Vista:  Windows NT 6.0
  • Windows 7      : Windows NT 6.1
  • Windows 8      : Windows NT 6.2

参考资料

  1. MSDN: Stream.Null 字段(System.IO)
  2. .NET Reflector
  3. Mono sources
posted on 2012-03-07 21:56  银河  阅读(3865)  评论(4编辑  收藏  举报