Mono源代码学习笔记:Console类(四)
来源:互联网 发布:中国数据库市场规模 编辑:程序博客网 时间:2024/05/16 05:30
NullStream 类 (internal class)
下面就是 mcs/class/corlib/System.IO/NullStream.cs:
01: namespace System.IO02: {03: class NullStream : Stream04: {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 中分离出来的,经过我的整理后就变成上面这个样子。从上述的源程序中可以看出:
- NullStream 类位于 System.IO 命名空间中。(第 1 行)
- NullStream 继承自抽象基类 Stream。(第 3 行)
- NullStream 是个 internal 类,只能用在本程序集中。(第 3 行)
- NullStream 有 12 个成员,全部是公共成员,用于重写抽象基类 Stream 的虚成员。(5 - 16 行)
- NullStream 有 5 个属性。这些属性的 get 方法仅返回零或者 true,仅有的一个 set 方法是空的。(5 - 9行)
- 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.IO02: {03: partial class Stream04: {05: private sealed class NullStream : Stream06: {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.IO02: {03: [Serializable]04: [ComVisible(true)]05: public abstract partial class Stream : MarshalByRefObject, IDisposable06: {07: public static readonly Stream Null = new NullStream();08: 09: //10: // 这里省略 Stream 类的其余成员11: //12: }13: }
如上述源程序第 5 行所示,加上 partial 关键字就行了。
第 7 行通过 Stream 类的 Null 公共只读静态字段对外公开了 NullStream 类。注意,这是 Stream.cs 中原来的代码,我没有作任何改动。
现在,其他程序要使用 NullStream 类,只有通过 Stream.Null 字段来使用了,这也是 NullStream 类的唯一实例。在我们的 Console.cs 中,原来是通过 new NullStream() 来使用 NullStream 类的,现在需要改为 Stream.Null 了。
这样做的好处是显而易见的:
- 我们对外隐藏了 NullStream 类,大家只需要知道 Stream.Null 这个公共只读静态字段好了。
- NullStream 类只被实例化一次,提高了效率。
- NullStream 类被声明为 sealed 的,可能对 C# 编译器以及 JIT 优化调用该类的虚方法的语句有好处。例如,有可能使用 call 指令代替 callvirt 指令。
这也实践了 Singleton 设计模式和 Null Object 设计模式。
UnexceptionalStreamReader 类 (internal class)
下面就是 mcs/class/corlib/System.IO/UnexceptionalStreamReader.cs:
001: //002: // System.IO.UnexceptionalStreamReader.cs003: //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.com011: // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)012: //013: // Permission is hereby granted, free of charge, to any person obtaining014: // a copy of this software and associated documentation files (the015: // "Software"), to deal in the Software without restriction, including016: // without limitation the rights to use, copy, modify, merge, publish,017: // distribute, sublicense, and/or sell copies of the Software, and to018: // permit persons to whom the Software is furnished to do so, subject to019: // the following conditions:020: // 021: // The above copyright notice and this permission notice shall be022: // 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 OF026: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND027: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE028: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION029: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION030: // 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 that035: // catches IOException so that graphical applications don't suddenly036: // get IO errors when their terminal vanishes. See037: // 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 overflow135: 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 类定义了以下两个私有静态字段:
- newline: private static,类型为 bool[]。(第 45 行)
- 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.cs003: //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.com010: //011: 012: //013: // Copyright (C) 2004 Novell, Inc (http://www.novell.com)014: //015: // Permission is hereby granted, free of charge, to any person obtaining016: // a copy of this software and associated documentation files (the017: // "Software"), to deal in the Software without restriction, including018: // without limitation the rights to use, copy, modify, merge, publish,019: // distribute, sublicense, and/or sell copies of the Software, and to020: // permit persons to whom the Software is furnished to do so, subject to021: // the following conditions:022: // 023: // The above copyright notice and this permission notice shall be024: // 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 OF028: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND029: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE030: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION031: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION032: // 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 that037: // catches IOException so that graphical applications don't suddenly038: // get IO errors when their terminal vanishes (ie when they spew debug039: // 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类(四)
- Mono源代码学习笔记:Console类(五)
- Mono源代码学习笔记:Console类(三)
- Mono学习笔记
- VINS mono 系统学习 四
- Java 学习笔记-IO-Console类
- NUnit学习笔记之Mono篇
- NUnit学习笔记之Mono篇
- NUnit学习笔记之Mono篇
- Web Server程序编写学习笔记(四)源代码
- 我的openwrt学习笔记(四):OpenWrt源代码下载
- Javascript学习笔记(console对象)
- 《C#入门到精通》学习笔记 -- Console类
- ATL窗口类源代码学习笔记
- ATL 窗口类源代码学习笔记
- 日历源代码学习笔记
- 源代码学习笔记
- nginx 源代码学习笔记
- Oracle语句优化规则汇总(8)
- Mono源代码学习笔记:Console类(五)
- SQL基础大集合
- OpenSSL库的RSA使用(下)-rsa函数方式
- iOS UI01_Label
- Mono源代码学习笔记:Console类(四)
- Oracle语句优化规则汇总(9)
- scikit-learn:3.4. Model persistence
- C 实现最小二乘,步骤以及代码
- Mono源代码学习笔记:Console类(三)
- 上位机学习笔记汇总
- Spring讲解------------本专栏代码包以及word版
- springMVC的全流程使用和分析
- Java 泛型的详解