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. 匿名訪问之(一)web application级别

    假设用SharePoint做一个对外开放的公共站点,比方公司展示站点.那么浏览站点的人不须要注冊和登陆.就应该能看到内容.这个时候就须要对站点开启匿名訪问. SharePoint的匿名訪问是从上而下的 ...

  2. sizeof()函数的使用——————【Badboy】

    1.sizeof的使用:sizeof操作符以字节形式给出了其操作数的存储大小. sizeof操作符不能用于函数类型,不全然类型或位字段.不全然类型指具有未知存储大小的数据类型,如未知存储大小的数组类型 ...

  3. java基础——static keyword小节

    static 用于修饰成员 修饰成员变量和成员函数 被修饰过的成员的特点:   1.随着类的载入而载入   2.优先于对象而存在   3.被全部对象所共享   4.能够直接被类名调用

  4. node--20 moogose demo2

    db.js /** * Created by Danny on 2015/9/28 16:44. */ //引包 var mongoose = require('mongoose'); //创建数据库 ...

  5. hdoj--5500--Reorder the Books(技巧)

    Reorder the Books Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  6. SPSS学习小记

    2013年1月8日 最近一直在SPSS中处理数据,涉及到函数部分,不是太懂,特记录于此,以便翻阅.   SPSS判断字符变量中是否含有某字符串的表示方式:  (INDEX(url,'ad')>0 ...

  7. C语言学习小记

    2013年1月31日 今天试着编程为报文去头去尾.   #include #include #define MAX_LENTH 1024 int main() {  char *path = &quo ...

  8. Spark 运行机制及原理分析

  9. 银行bank系统项目实践

    想看项目的注意了!完整版银行管理系统就在这里看不看你看着办! 按照惯例咱们还是先来看一下项目需求: 某银行为了提高业务率希望开发一个银行管理系统功能如下: 1.能够完成用户开户操作 2.能够完成用户取 ...

  10. 【原创】JMS生产者和消费者【PTP异步接收消息】

    PTP模式下,异步接收消息需要定义一个MessageListener来监听,当生产者有消息要发送时会主动通知Listener去处理该消息,会调用监听的onMessage方法去处理. 首先看生产者(和同 ...