NullStream 类 (internal class)

以下就是 mcs/class/corlib/System.IO/NullStream.cs:

01:  namespace System.IO
02: {
03: class NullStream : Stream
04: {
05: public override bool CanRead { get { return true; } }
06: public override bool CanSeek { get { return true; } }
07: public override bool CanWrite { get { return true; } }
08: public override long Length { get { return 0; } }
09: public override long Position { get { return 0; } set { } }
10: public override void Flush() { }
11: public override int Read(byte[] buffer, int offset, int count) { return 0; }
12: public override int ReadByte() { return -1; }
13: public override long Seek(long offset, SeekOrigin origin) { return 0; }
14: public override void SetLength(long value) { }
15: public override void Write(byte[] buffer, int offset, int count) { }
16: public override void WriteByte(byte value) { }
17: }
18: }

上述源程序定义了 NullStream 类。我在我个系列学习笔记第一篇中谈到。这个 NullStream 类是从 Stream.cs 中分离出来的,经过我的整理后就变成上面这个样子。从上述的源程序中能够看出:

  1. NullStream 类位于 System.IO 命名空间中。

    (第 1 行)

  2. NullStream 继承自抽象基类 Stream。(第 3 行)
  3. NullStream 是个 internal 类,仅仅能用在本程序集中。(第 3 行)
  4. NullStream 有 12 个成员,所有是公共成员,用于重写抽象基类 Stream 的虚成员。

    (5 - 16 行)

  5. NullStream 有 5 个属性。

    这些属性的 get 方法仅返回零或者 true,仅有的一个 set 方法是空的。(5 - 9行)

  6. NullStream 有 7 个方法。这方法要么是空的。要么仅返回零或者 -1。(10 – 16 行)

NullStream 类实践了 Null Object 设计模式。

因为 NullStream 类是作为 Null Object 使用的,它能够不重写抽象基类 Stream 的 ReadByte 方法(第 12 行)和 WriteByte 方法(第
16 行),由于 Stream 的这两个方法都是虚(virtual)方法,而不是抽象(abstract)方法。

以下就是 Mono 源码中的 mcs/class/corlib/System.IO/Stream.cs 文件里 Stream 类的这两个虚方法的代码:

01:  public virtual int ReadByte()
02: {
03: byte[] buffer = new byte[1];
04: if (Read(buffer, 0, 1) == 1) return buffer[0];
05: return -1;
06: }
07:
08: public virtual void WriteByte(byte value)
09: {
10: byte[] buffer = new byte[1];
11: buffer[0] = value;
12: Write(buffer, 0, 1);
13: }

能够看出,Stream 类的 ReadByte 方法创建一个新的单字节数组,然后调用 Read 方法(第 3 行到第 5 行)。Stream 类的 WriteByte 方法创建一个新的单字节数组,然后调用 Write 方法(第 10 行到第 12 行)。也就是说,假设 NullStream 类不重写抽象基类 Stream 的 ReadByte 方法和 WriteByte 方法。得到的执行结果也是一样的。

可是。这样效率就低了非常多。

在 Console.dll 项目中,NullStream 类仅在 Console.cs 中被使用过一次。

对 NullStream 类的改进建议

我建议将 mcs/class/corlib/System.IO/NullStream.cs 改为例如以下所看到的:

01:  namespace System.IO
02: {
03: partial class Stream
04: {
05: private sealed class NullStream : Stream
06: {
07: public override bool CanRead { get { return true; } }
08: public override bool CanSeek { get { return true; } }
09: public override bool CanWrite { get { return true; } }
10: public override long Length { get { return 0; } }
11: public override long Position { get { return 0; } set { } }
12: public override void Flush() { }
13: public override int Read(byte[] buffer, int offset, int count) { return 0; }
14: public override int ReadByte() { return -1; }
15: public override long Seek(long offset, SeekOrigin origin) { return 0; }
16: public override void SetLength(long value) { }
17: public override void Write(byte[] buffer, int offset, int count) { }
18: public override void WriteByte(byte value) { }
19: }
20: }
21: }

也就是说,将 NullStream 类从 System.IO 命名空间中的 internal 类更改为 System.IO.Stream 类的私有(private)密封(sealed)内嵌类(请參阅上述源程序第 5 行)。而 mcs/class/corlib/System.IO/Stream.cs 仅仅需作例如以下修改:

01:  namespace System.IO
02: {
03: [Serializable]
04: [ComVisible(true)]
05: public abstract partial class Stream : MarshalByRefObject, IDisposable
06: {
07: public static readonly Stream Null = new NullStream();
08:
09: //
10: // 这里省略 Stream 类的其余成员
11: //
12: }
13: }

如上述源程序第 5 行所看到的。加上 partial keyword即可了。

第 7 行通过 Stream 类的 Null 公共仅仅读静态字段对外公开了 NullStream 类。

注意。这是 Stream.cs 中原来的代码。我没有作不论什么修改。

如今。其它程序要使用 NullStream 类。仅仅有通过 Stream.Null 字段来使用了,这也是 NullStream 类的唯一实例。在我们的 Console.cs 中。原来是通过 new NullStream()
来使用 NullStream 类的,如今须要改为 Stream.Null 了。

这样做的优点是显而易见的:

  1. 我们对外隐藏了 NullStream 类。大家仅仅须要知道 Stream.Null 这个公共仅仅读静态字段好了。
  2. NullStream 类仅仅被实例化一次,提高了效率。
  3. NullStream 类被声明为 sealed 的。可能对 C# 编译器以及 JIT 优化调用该类的虚方法的语句有优点。

    比如,有可能使用 call 指令取代 callvirt 指令。

这也实践了 Singleton 设计模式和 Null Object 设计模式。

UnexceptionalStreamReader 类 (internal class)

以下就是 mcs/class/corlib/System.IO/UnexceptionalStreamReader.cs:

001:  //
002: // System.IO.UnexceptionalStreamReader.cs
003: //
004: // Authors:
005: // Dietmar Maurer (dietmar@ximian.com)
006: // Miguel de Icaza (miguel@ximian.com)
007: // Dick Porter (dick@ximian.com)
008: // Sebastien Pouliot <sebastien@ximian.com>
009: //
010: // (C) Ximian, Inc. http://www.ximian.com
011: // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
012: //
013: // Permission is hereby granted, free of charge, to any person obtaining
014: // a copy of this software and associated documentation files (the
015: // "Software"), to deal in the Software without restriction, including
016: // without limitation the rights to use, copy, modify, merge, publish,
017: // distribute, sublicense, and/or sell copies of the Software, and to
018: // permit persons to whom the Software is furnished to do so, subject to
019: // the following conditions:
020: //
021: // The above copyright notice and this permission notice shall be
022: // included in all copies or substantial portions of the Software.
023: //
024: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
025: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
026: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
027: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
028: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
029: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
030: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
031: //
032:
033:
034: // This is a wrapper around StreamReader used by System.Console that
035: // catches IOException so that graphical applications don't suddenly
036: // get IO errors when their terminal vanishes. See
037: // UnexceptionalStreamWriter too.
038:
039: using System.Text;
040: using System.Runtime.InteropServices;
041:
042: namespace System.IO {
043: internal class UnexceptionalStreamReader : StreamReader {
044:
045: private static bool[] newline = new bool [Environment.NewLine.Length];
046:
047: private static char newlineChar;
048:
049: static UnexceptionalStreamReader () {
050: string n = Environment.NewLine;
051: if (n.Length == 1)
052: newlineChar = n [0];
053: }
054:
055: public UnexceptionalStreamReader(Stream stream)
056: : base (stream)
057: {
058: }
059:
060: public UnexceptionalStreamReader(Stream stream, bool detect_encoding_from_bytemarks)
061: : base (stream, detect_encoding_from_bytemarks)
062: {
063: }
064:
065: public UnexceptionalStreamReader(Stream stream, Encoding encoding)
066: : base (stream, encoding)
067: {
068: }
069:
070: public UnexceptionalStreamReader(Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks)
071: : base (stream, encoding, detect_encoding_from_bytemarks)
072: {
073: }
074:
075: public UnexceptionalStreamReader(Stream stream, Encoding encoding, bool detect_encoding_from_bytemarks, int buffer_size)
076: : base (stream, encoding, detect_encoding_from_bytemarks, buffer_size)
077: {
078: }
079:
080: public UnexceptionalStreamReader(string path)
081: : base (path)
082: {
083: }
084:
085: public UnexceptionalStreamReader(string path, bool detect_encoding_from_bytemarks)
086: : base (path, detect_encoding_from_bytemarks)
087: {
088: }
089:
090: public UnexceptionalStreamReader(string path, Encoding encoding)
091: : base (path, encoding)
092: {
093: }
094:
095: public UnexceptionalStreamReader(string path, Encoding encoding, bool detect_encoding_from_bytemarks)
096: : base (path, encoding, detect_encoding_from_bytemarks)
097: {
098: }
099:
100: public UnexceptionalStreamReader(string path, Encoding encoding, bool detect_encoding_from_bytemarks, int buffer_size)
101: : base (path, encoding, detect_encoding_from_bytemarks, buffer_size)
102: {
103: }
104:
105: public override int Peek ()
106: {
107: try {
108: return(base.Peek ());
109: } catch (IOException) {
110: }
111:
112: return(-1);
113: }
114:
115: public override int Read ()
116: {
117: try {
118: return(base.Read ());
119: } catch (IOException) {
120: }
121:
122: return(-1);
123: }
124:
125: public override int Read ([In, Out] char[] dest_buffer,
126: int index, int count)
127: {
128: if (dest_buffer == null)
129: throw new ArgumentNullException ("dest_buffer");
130: if (index < 0)
131: throw new ArgumentOutOfRangeException ("index", "< 0");
132: if (count < 0)
133: throw new ArgumentOutOfRangeException ("count", "< 0");
134: // ordered to avoid possible integer overflow
135: if (index > dest_buffer.Length - count)
136: throw new ArgumentException ("index + count > dest_buffer.Length");
137:
138: int chars_read = 0;
139: char nl = newlineChar;
140: try {
141: while (count > 0) {
142: int c = base.Read ();
143: if (c < 0)
144: break;
145: chars_read++;
146: count--;
147:
148: dest_buffer [index] = (char) c;
149: // shortcut when a new line is only one character (e.g. Linux, Mac)
150: if (nl != (char)0) {
151: if ((char)c == nl)
152: return chars_read;
153: } else {
154: if (CheckEOL ((char)c))
155: return chars_read;
156: }
157: index ++;
158: }
159: } catch (IOException) {
160: }
161:
162: return chars_read;
163: }
164:
165: private bool CheckEOL (char current)
166: {
167: // general case for any length (e.g. Windows)
168: for (int i=0; i < newline.Length; i++) {
169: if (!newline [i]) {
170: if (current == Environment.NewLine [i]) {
171: newline [i] = true;
172: return (i == newline.Length - 1);
173: }
174: break;
175: }
176: }
177: for (int j=0; j < newline.Length; j++)
178: newline [j] = false;
179: return false;
180: }
181:
182: public override string ReadLine()
183: {
184: try {
185: return(base.ReadLine ());
186: } catch (IOException) {
187: }
188:
189: return(null);
190: }
191:
192: public override string ReadToEnd()
193: {
194: try {
195: return(base.ReadToEnd ());
196: } catch (IOException) {
197: }
198:
199: return(null);
200: }
201: }
202: }

上述源程序定义了 UnexceptionalStreamReader 类。该类位于 System.IO 命名空间中,继承自 StreamReader 类。是 internal 的。即仅仅能在本程序集中使用。

UnexceptionalStreamReader 类是对 StreamReader 类的包装,捕获并忽略全部的 IOException 异常。它用于 Console 类中,以免 IO 错误干扰控制台的正常执行。

UnexceptionalStreamReader 类定义了下面两个私有静态字段:

  1. newline: private static,类型为 bool[]。

    (第 45 行)

  2. newlineChar: private static。类型为 char。(第 47 行)

第 49 行到第 53 行的静态构造函数对 newlineChar 字段有条件地赋值。

第 55 行到第 103 行的十个构造函数仅是调用基类 StreamReader 对应的构造函数而已。

第 105 行到第 123 行以及第 182 行到第 200 行的四个方法重写了基类 StreamReader 中对应的虚方法。简单地调用基类中对应的虚方法,捕获并忽略 IOException 异常。

第 125 行到第 163 行的 Read 方法也是重写了基类的虚方法,可是它没有简单地调用基类中对应的虚方法。

它首先检查输入的參数是否合法。然后在循环中调用基类的还有一个 Read 方法一个个地读取字符,捕获并忽略 IOException 异常。注意这个 Read 方法的语义不同于其基类 StreamReader 中对应的 Read 方法的语义,前者遇到 EOL 就提前返回,而后者要遇到 EOF
才会提前返回。

第 165 行到第 180 行的 CheckEOL 方法是私有(private)方法,仅在第 154 行被调用过,用于在 Environment.NewLine 不止一个字符时(在 Windows
操作系统中就是如此。其值为”\r\n”,而在 Unix 操作系统中其值为”\n”)推断是否遇到了行结束符。即 EOL,也就是 Environment.NewLine。

在 Console.dll 项目中。UnexceptionalStreamReader 类在 Console.cs 中被使用过一次。

在上述源程序的第 34 行到第 37 行的凝视中也已经指出了这一点。

UnexceptionalStreamWriter 类 (internal class)

以下就是 mcs/class/corlib/System.IO/UnexceptionalStreamWriter.cs:

001:  //
002: // System.IO.StreamWriter.cs
003: //
004: // Authors:
005: // Dietmar Maurer (dietmar@ximian.com)
006: // Paolo Molaro (lupus@ximian.com)
007: // Dick Porter (dick@ximian.com)
008: //
009: // (C) Ximian, Inc. http://www.ximian.com
010: //
011:
012: //
013: // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
014: //
015: // Permission is hereby granted, free of charge, to any person obtaining
016: // a copy of this software and associated documentation files (the
017: // "Software"), to deal in the Software without restriction, including
018: // without limitation the rights to use, copy, modify, merge, publish,
019: // distribute, sublicense, and/or sell copies of the Software, and to
020: // permit persons to whom the Software is furnished to do so, subject to
021: // the following conditions:
022: //
023: // The above copyright notice and this permission notice shall be
024: // included in all copies or substantial portions of the Software.
025: //
026: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
027: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
028: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
029: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
030: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
031: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
032: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
033: //
034:
035:
036: // This is a wrapper around StreamWriter used by System.Console that
037: // catches IOException so that graphical applications don't suddenly
038: // get IO errors when their terminal vanishes (ie when they spew debug
039: // output.) See UnexceptionalStreamReader too.
040:
041: using System.Text;
042: using System;
043:
044: namespace System.IO {
045: internal class UnexceptionalStreamWriter: StreamWriter {
046: public UnexceptionalStreamWriter (Stream stream)
047: : base (stream)
048: {
049: }
050:
051: public UnexceptionalStreamWriter (Stream stream,
052: Encoding encoding)
053: : base (stream, encoding)
054: {
055: }
056:
057: public UnexceptionalStreamWriter (Stream stream,
058: Encoding encoding,
059: int bufferSize)
060: : base (stream, encoding, bufferSize)
061: {
062: }
063:
064: public UnexceptionalStreamWriter (string path)
065: : base (path)
066: {
067: }
068:
069: public UnexceptionalStreamWriter (string path, bool append)
070: : base (path, append)
071: {
072: }
073:
074: public UnexceptionalStreamWriter (string path, bool append,
075: Encoding encoding)
076: : base (path, append, encoding)
077: {
078: }
079:
080: public UnexceptionalStreamWriter (string path, bool append,
081: Encoding encoding,
082: int bufferSize)
083: : base (path, append, encoding, bufferSize)
084: {
085: }
086:
087: public override void Flush ()
088: {
089: try {
090: base.Flush ();
091: } catch (Exception) {
092: }
093: }
094:
095: public override void Write (char[] buffer, int index,
096: int count)
097: {
098: try {
099: base.Write (buffer, index, count);
100: } catch (IOException) {
101: }
102: }
103:
104: public override void Write (char value)
105: {
106: try {
107: base.Write (value);
108: } catch (IOException) {
109: }
110: }
111:
112: public override void Write (char[] value)
113: {
114: try {
115: base.Write (value);
116: } catch (IOException) {
117: }
118: }
119:
120: public override void Write (string value)
121: {
122: try {
123: base.Write (value);
124: } catch (IOException) {
125: }
126: }
127: }
128: }

上述源程序定义了 UnexceptionStreamWriter 类。该类位于 System.IO 命名空间中,继承自 StreamWriter 类,是 internal 的。即仅仅能在本程序集中使用。

第 2 行的凝视“System.IO.StreamWriter.cs”有误,应改为“System.IO.UnexceptionStreamWriter”。

UnexceptionalStreamWriter 类是对 StreamWriter 类的包装,捕获并忽略全部的 IOException 异常。

它用于 Console 类中。以免 IO 错误干扰控制台的正常执行。

第 46 行到第 85 行的七个构造函数仅是调用基类 StreamWriter 对应的构造函数而已。

第 87 行到第 126 行的五个方法重写了基类 StreamWriter 中对应的虚方法,简单地调用基类中对应的虚方法,捕获并忽略 IOException 异常。

在 Console.dll 项目中,UnexceptionStreamWriter 类在 Console.cs 中被使用过两次。

Mono源码学习笔记:Console类(四)的更多相关文章

  1. Mono源码学习笔记:Console类(三)

    Buffer 类 (public static class) 以下就是 mcs/class/corlib/System/Buffer.cs: 001: // 002: // System.Buffer ...

  2. Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

    Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...

  3. async-validator 源码学习笔记(四):validator

    系列文章: 1.async-validator 源码学习(一):文档翻译 2.async-validator 源码学习笔记(二):目录结构 3.async-validator 源码学习笔记(三):ru ...

  4. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  5. async-validator 源码学习笔记(五):Schema

    系列文章: 1.async-validator 源码学习(一):文档翻译 2.async-validator 源码学习笔记(二):目录结构 3.async-validator 源码学习笔记(三):ru ...

  6. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

  7. Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

    Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...

  8. JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...

  9. JUC源码学习笔记4——原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法

    JUC源码学习笔记4--原子类,CAS,Volatile内存屏障,缓存伪共享与UnSafe相关方法 volatile的原理和内存屏障参考<Java并发编程的艺术> 原子类源码基于JDK8 ...

随机推荐

  1. tp框架报错 Namespace declaration statement has to be the very first statement in the script

    Namespace declaration statement has to be the very first statement in the script tp框架报这个错误,错误行数就是nam ...

  2. windows部署iBase4J

    所需环境:jdk 1.8.eclipse(myeclipse不可以).nginx.activeMQ .zookeeper.redis 第一步 下载jdk1.8 按步骤安装至指定位置即可 第二步 安装e ...

  3. 学一下HDFS,很不错(大数据技术原理及应用)

    http://study.163.com/course/courseMain.htm?courseId=1002887002 里面的HDFS这一部分.

  4. POJ 2084

    第一题组合数学题.可以使用递推,设1与其他各数分别连边,假设N=3;若1-4,则圆分成两部分计数,此时可以利用乘法原理.(高精度) #include <cstdio> #include & ...

  5. Android应用常规开发技巧——善用组件生命周期

    数据管理 对于仅仅读数据.一种经常使用的管理模式是在onCreate函数中进行数据的载入,直到组件的onDestory函数被调用时在进行释放. // 缓存仅仅读的数据 private Object r ...

  6. Dalvik虚拟机垃圾收集(GC)过程分析

    前面我们分析了Dalvik虚拟机堆的创建过程,以及Java对象在堆上的分配过程. 这些知识都是理解Dalvik虚拟机垃圾收集过程的基础.垃圾收集是一个复杂的过程,它要将那些不再被引用的对象进行回收.一 ...

  7. python学习之--安装IDE(eclipse+pydev)

    First steps download eclipse url:http://www.eclipse.org/downloads/ select Help -> Install New Sof ...

  8. shareSDK的初步使用(shareSDK中微信、qq等兼容问题,以及cocoapods支持架构冲突问题的解决)

    第一次使用shareSDK来做第三方分享,可是.昨天一天都是在调试bug,一直错误不断! 先说下我的开发环境: xcode:5.1 真机调试:iPhone5s 我们都知道xcode5.1以后開始是支持 ...

  9. scanf正则表达式

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { ] = ...

  10. Linux换行符相关

    Linux和windows中的换行符差异问题LINUX的换行符在Windows记事本打开不换行或出现黑点是由于Linux和windows中的换行符差异问题造成的. Unix系统里,每行结尾只有“< ...