Buffer 类 (public static class)
下面就是 mcs/class/corlib/System/Buffer.cs:
001: // 002: // System.Buffer.cs 003: // 004: // Authors: 005: // Paolo Molaro (lupus@ximian.com) 006: // Dan Lewis (dihlewis@yahoo.co.uk) 007: // 008: // (C) 2001 Ximian, Inc. http://www.ximian.com 009: // 010: 011: // 012: // Copyright (C) 2004 Novell, Inc (http://www.novell.com) 013: // 014: // Permission is hereby granted, free of charge, to any person obtaining 015: // a copy of this software and associated documentation files (the 016: // "Software"), to deal in the Software without restriction, including 017: // without limitation the rights to use, copy, modify, merge, publish, 018: // distribute, sublicense, and/or sell copies of the Software, and to 019: // permit persons to whom the Software is furnished to do so, subject to 020: // the following conditions: 021: // 022: // The above copyright notice and this permission notice shall be 023: // included in all copies or substantial portions of the Software. 024: // 025: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 026: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 027: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 028: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 029: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 030: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 031: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 032: // 033: 034: using System.Runtime.CompilerServices; 035: using System.Runtime.InteropServices; 036: 037: namespace System { 038: [ComVisible (true)] 039: public static class Buffer { 040: 041: public static int ByteLength (Array array) 042: { 043: // note: the other methods in this class also use ByteLength to test for 044: // null and non-primitive arguments as a side-effect. 045: 046: if (array == null) 047: throw new ArgumentNullException ("array"); 048: 049: int length = ByteLengthInternal (array); 050: if (length < 0) 051: throw new ArgumentException (Locale.GetText ("Object must be an array of primitives.")); 052: 053: return length; 054: } 055: 056: public static byte GetByte (Array array, int index) 057: { 058: if (index < 0 || index >= ByteLength (array)) 059: throw new ArgumentOutOfRangeException ("index", Locale.GetText( 060: "Value must be non-negative and less than the size of the collection.")); 061: 062: return GetByteInternal (array, index); 063: } 064: 065: public static void SetByte (Array array, int index, byte value) 066: { 067: if (index < 0 || index >= ByteLength (array)) 068: throw new ArgumentOutOfRangeException ("index", Locale.GetText( 069: "Value must be non-negative and less than the size of the collection.")); 070: 071: SetByteInternal (array, index, value); 072: } 073: 074: public static void BlockCopy (Array src, int srcOffset, Array dst, int dstOffset, int count) 075: { 076: if (src == null) 077: throw new ArgumentNullException ("src"); 078: 079: if (dst == null) 080: throw new ArgumentNullException ("dst"); 081: 082: if (srcOffset < 0) 083: throw new ArgumentOutOfRangeException ("srcOffset", Locale.GetText( 084: "Non-negative number required.")); 085: 086: if (dstOffset < 0) 087: throw new ArgumentOutOfRangeException ("dstOffset", Locale.GetText ( 088: "Non-negative number required.")); 089: 090: if (count < 0) 091: throw new ArgumentOutOfRangeException ("count", Locale.GetText ( 092: "Non-negative number required.")); 093: 094: // We do the checks in unmanaged code for performance reasons 095: bool res = BlockCopyInternal (src, srcOffset, dst, dstOffset, count); 096: if (!res) { 097: // watch for integer overflow 098: if ((srcOffset > ByteLength (src) - count) || (dstOffset > ByteLength (dst) - count)) 099: throw new ArgumentException (Locale.GetText ( 100: "Offset and length were out of bounds for the array or count is greater than " + 101: "the number of elements from index to the end of the source collection.")); 102: } 103: } 104: 105: // private 106: [MethodImplAttribute (MethodImplOptions.InternalCall)] 107: private extern static int ByteLengthInternal (Array array); 108: 109: [MethodImplAttribute (MethodImplOptions.InternalCall)] 110: private extern static byte GetByteInternal (Array array, int index); 111: 112: [MethodImplAttribute (MethodImplOptions.InternalCall)] 113: private extern static void SetByteInternal (Array array, int index, int value); 114: 115: [MethodImplAttribute (MethodImplOptions.InternalCall)] 116: internal extern static bool BlockCopyInternal (Array src, int src_offset, Array dest, int dest_offset, int count); 117: } 118: }
上述源程序定义了 Buffer 类。这是一个公共静态类,用于操作基元类型的数组,数组中的每个基元类型都被视为一系列字节。它的公共成员只有以下四个公共静态方法,这些方法比 System.Array 类中相似的方法提供更好的性能:
- BtyeLength: public static,返回指定数组中的字节数。(41 – 54 行)
- GetByte: public static,在指定数组中检索指定位置处的字节。(56 – 63 行)
- SetByte: public static,将指定的值分配给指定数组中特定位置处的字节。(65 – 72 行)
- BlockCopy: public static,将指定数目的字节从起始于特定偏移量的源数组复制到起始于特定偏移量的目标数组。(74 – 103 行)
上述四个方法仅仅是在作一些必要的参数检查后调用下述四个非公共的外部静态方法:
- ByteLengthInternal: private extern static (106 – 107 行)
- GetByteInternal: private extern static (109 – 110 行)
- SetByteInternal: private extern static (112 –114 行)
- BlockCopyInternal: internal extern static (115 – 116 行)
上述四个方法都被标记为 [MethodImpl(MethodImplOptions.InternalCall)],也就是说,这四个方法都是对在公共语言运行时本身内部实现的方法的调用。请注意 BlockCopyInternal 方法是 internal 的,而不象其他三个方法那样是 private 的。实际上,在 Console.dll 项目中,BlockCopyInternal 方法在 TermInfoReader.cs 中被调用。而 Buffer 类的四个公共方法在 Console.dll 项目中都没有被调用。
IConsoleDriver 接口 (internal interface)
下面就是 mcs/class/corlib/System/IConsoleDriver.cs:
01: // 02: // System.IConsoleDriver 03: // 04: // Author: 05: // Gonzalo Paniagua Javier (gonzalo@ximian.com) 06: // 07: // (C) 2005 Novell, Inc. (http://www.novell.com) 08: // 09: 10: // Permission is hereby granted, free of charge, to any person obtaining 11: // a copy of this software and associated documentation files (the 12: // "Software"), to deal in the Software without restriction, including 13: // without limitation the rights to use, copy, modify, merge, publish, 14: // distribute, sublicense, and/or sell copies of the Software, and to 15: // permit persons to whom the Software is furnished to do so, subject to 16: // the following conditions: 17: // 18: // The above copyright notice and this permission notice shall be 19: // included in all copies or substantial portions of the Software. 20: // 21: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28: // 29: namespace System { 30: interface IConsoleDriver { 31: ConsoleColor BackgroundColor { get; set; } 32: int BufferHeight { get; set; } 33: int BufferWidth { get; set; } 34: bool CapsLock { get; } 35: int CursorLeft { get; set; } 36: int CursorSize { get; set; } 37: int CursorTop { get; set; } 38: bool CursorVisible { get; set; } 39: ConsoleColor ForegroundColor { get; set; } 40: bool KeyAvailable { get; } 41: bool Initialized { get; } 42: int LargestWindowHeight { get; } 43: int LargestWindowWidth { get; } 44: bool NumberLock { get; } 45: string Title { get; set; } 46: bool TreatControlCAsInput { get; set; } 47: int WindowHeight { get; set; } 48: int WindowLeft { get; set; } 49: int WindowTop { get; set; } 50: int WindowWidth { get; set; } 51: 52: void Init (); 53: void Beep (int frequency, int duration); 54: void Clear (); 55: void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, 56: int targetLeft, int targetTop, Char sourceChar, 57: ConsoleColor sourceForeColor, ConsoleColor sourceBackColor); 58: 59: ConsoleKeyInfo ReadKey (bool intercept); 60: void ResetColor (); 61: void SetBufferSize (int width, int height); 62: void SetCursorPosition (int left, int top); 63: void SetWindowPosition (int left, int top); 64: void SetWindowSize (int width, int height); 65: string ReadLine (); 66: } 67: }
上述源程序定义了 IConsoleDriver 接口。上述源程序第 30 行没有明确指出访问修饰符,那么这个接口默认为 internal 的,只能在本程序集中使用。IConsoleDriver 接口是我在这个系列学习笔记第一篇的末尾指出的六个最核心的类型之一,它规定了所有的控制台都必须实现的基本功能。IConsoleDriver 共定义了 11 个方法,20 个属性,其中 6 个是只读属性。
NullConsoleDriver 类 (internal class)
下面就是 mcs/class/corlib/System/NullConsoleDriver.cs:
001: // 002: // System.NullConsoleDriver 003: // 004: // Author: 005: // Gonzalo Paniagua Javier (gonzalo@ximian.com) 006: // 007: // (C) 2006 Novell, Inc. (http://www.novell.com) 008: // 009: 010: // Permission is hereby granted, free of charge, to any person obtaining 011: // a copy of this software and associated documentation files (the 012: // "Software"), to deal in the Software without restriction, including 013: // without limitation the rights to use, copy, modify, merge, publish, 014: // distribute, sublicense, and/or sell copies of the Software, and to 015: // permit persons to whom the Software is furnished to do so, subject to 016: // the following conditions: 017: // 018: // The above copyright notice and this permission notice shall be 019: // included in all copies or substantial portions of the Software. 020: // 021: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 022: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 023: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 024: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 025: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 026: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 027: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 028: // 029: #if !NET_2_1 030: using System.Runtime.InteropServices; 031: using System.Text; 032: namespace System { 033: class NullConsoleDriver : IConsoleDriver { 034: public ConsoleColor BackgroundColor { 035: get { return ConsoleColor.Black; } 036: set { 037: } 038: } 039: 040: public int BufferHeight { 041: get { return 0; } 042: set {} 043: } 044: 045: public int BufferWidth { 046: get { return 0; } 047: set {} 048: } 049: 050: public bool CapsLock { 051: get { return false; } 052: } 053: 054: public int CursorLeft { 055: get { return 0; } 056: set {} 057: } 058: 059: public int CursorSize { 060: get { return 0; } 061: set { } 062: } 063: 064: public int CursorTop { 065: get { return 0; } 066: set {} 067: } 068: 069: public bool CursorVisible { 070: get { return false; } 071: set {} 072: } 073: 074: public ConsoleColor ForegroundColor { 075: get { return ConsoleColor.Black; } 076: set {} 077: } 078: 079: public bool KeyAvailable { 080: get { return false; } // FIXME: throw? 081: } 082: 083: public bool Initialized { 084: get { return true; } 085: } 086: 087: public int LargestWindowHeight { 088: get { return 0; } 089: } 090: 091: public int LargestWindowWidth { 092: get { return 0; } 093: } 094: 095: public bool NumberLock { 096: get { return false; } 097: } 098: 099: public string Title { 100: get { return ""; } 101: set {} 102: } 103: 104: public bool TreatControlCAsInput { 105: get { return false; } 106: set {} 107: } 108: 109: public int WindowHeight { 110: get { return 0; } 111: set {} 112: } 113: 114: public int WindowLeft { 115: get { return 0; } 116: set {} 117: } 118: 119: public int WindowTop { 120: get { return 0; } 121: set {} 122: } 123: 124: public int WindowWidth { 125: get { return 0; } 126: set {} 127: } 128: 129: public void Beep (int frequency, int duration) 130: { 131: } 132: 133: public void Clear () 134: { 135: } 136: 137: public void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, 138: int targetLeft, int targetTop, Char sourceChar, 139: ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) 140: { 141: } 142: 143: public void Init () 144: { 145: } 146: 147: public string ReadLine () 148: { 149: return null; 150: } 151: 152: public ConsoleKeyInfo ReadKey (bool intercept) 153: { 154: return ConsoleKeyInfo.Empty; 155: } 156: 157: public void ResetColor () 158: { 159: } 160: 161: public void SetBufferSize (int width, int height) 162: { 163: } 164: 165: public void SetCursorPosition (int left, int top) 166: { 167: } 168: 169: public void SetWindowPosition (int left, int top) 170: { 171: } 172: 173: public void SetWindowSize (int width, int height) 174: { 175: } 176: } 177: } 178: #endif
上述源程序定义了 NullConsoleDriver 类。整个源程序(除了开头的注释以外)被第 29 行的“#if !NET_2_1” 和第 178 行的“#endif”预处理指令括了起来,表明该类不能用在 Moonlight 中,实际上 Moonlight 是应用于 Web 的,不需要控制台的概念。这里的 NET_2_1 表示 .NET 2.1,而 Moonlight 是基于 .NET 2.1 的,具体请参见:MoonlightNotes。
从上述源程序可以看出,该类的所有成员都是 public 的,而且刚好有 31 个成员,仅仅是满足 IConsoleDriver 接口的要求。
第 34 行到第 127 行是 20 个属性,这些属性的 set 方法(如果不是只读属性的话)都是空的,get 方法也仅仅是返回空字符串、零、null、false、true、或者 ConsoleColor.Black。
第 129 行到第 176 行是 11 个方法,这些方法或者是空的,或者仅仅返回 null 或者 ConsoleKeyInfo.Empty。
NullConsoleDriver 类实践了 Null Object 设计模式。
在 Console.dll 项目中,NullConsoleDriver 类仅在 ConsoleDriver.cs 中被使用过一次。
(未完待续)