上图中有大量的类、结构、枚举和委托,其中绝大部分都是 internal 或者 private 的,也就是说只能在本程序集内部使用,对外是不可见的。
我们先从简单的,为别的类型所使用的类型开始阅读源代码吧。
Locale 类 (internal sealed class)
现在来看看 mcs/build/common/Locale.cs:
01: // 02: // Locale.cs 03: // 04: // Author: 05: // Miguel de Icaza (miguel@ximian.com) 06: // Andreas Nahr (ClassDevelopment@A-SoftTech.com) 07: // 08: // (C) 2001 - 2003 Ximian, Inc (http://www.ximian.com) 09: // 10: 11: // 12: // Copyright (C) 2004 Novell, Inc (http://www.novell.com) 13: // 14: // Permission is hereby granted, free of charge, to any person obtaining 15: // a copy of this software and associated documentation files (the 16: // "Software"), to deal in the Software without restriction, including 17: // without limitation the rights to use, copy, modify, merge, publish, 18: // distribute, sublicense, and/or sell copies of the Software, and to 19: // permit persons to whom the Software is furnished to do so, subject to 20: // the following conditions: 21: // 22: // The above copyright notice and this permission notice shall be 23: // included in all copies or substantial portions of the Software. 24: // 25: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32: // 33: 34: using System; 35: 36: internal sealed class Locale { 37: 38: private Locale () 39: { 40: } 41: 42: public static string GetText (string msg) 43: { 44: return msg; 45: } 46: 47: public static string GetText (string fmt, params object [] args) 48: { 49: return String.Format (fmt, args); 50: } 51: }
这个 Locale 类被修饰为 internal,只能在本程序集内部使用。它也是一个密封类,并且构造函数只有一个私有的,因此它即不能被继承,也无法创建该类的实例。它目前仅有的两个方法都是静态的。我不明白为什么 Miguel de Icaza 和 Andreas Nahr 不干脆把它声明为静态类。此外,这个类位于全局命名空间中,这也不是好的做法。
从这个类的名称 Locale 和它现有的两个静态方法 GetText 来看,它是用来提供本地化的功能的。目前并没有实现任何本地化的功能,仅仅是简单地将输入的字符串原样返回而已。
在 Console.dll 这个项目中,Locale 类仅在 Buffer.cs 中使用过七次。
MonoTODOAttributes 类及其派生类 (internal class)
下面是 mcs/build/common/MonoTODOAttribute.cs:
001: // 002: // MonoTODOAttribute.cs 003: // 004: // Authors: 005: // Ravi Pratap (ravi@ximian.com) 006: // Eyal Alaluf <eyala@mainsoft.com> 007: // 008: // (C) Ximian, Inc. http://www.ximian.com 009: // 010: 011: // 012: // Copyright (C) 2004 Novell, Inc (http://www.novell.com) 013: // Copyright (C) 2006 Mainsoft, Inc (http://www.mainsoft.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: namespace System { 036: 037: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 038: internal class MonoTODOAttribute : Attribute { 039: 040: string comment; 041: 042: public MonoTODOAttribute () 043: { 044: } 045: 046: public MonoTODOAttribute (string comment) 047: { 048: this.comment = comment; 049: } 050: 051: public string Comment { 052: get { return comment; } 053: } 054: } 055: 056: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 057: internal class MonoDocumentationNoteAttribute : MonoTODOAttribute { 058: 059: public MonoDocumentationNoteAttribute (string comment) 060: : base (comment) 061: { 062: } 063: } 064: 065: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 066: internal class MonoExtensionAttribute : MonoTODOAttribute { 067: 068: public MonoExtensionAttribute (string comment) 069: : base (comment) 070: { 071: } 072: } 073: 074: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 075: internal class MonoInternalNoteAttribute : MonoTODOAttribute { 076: 077: public MonoInternalNoteAttribute (string comment) 078: : base (comment) 079: { 080: } 081: } 082: 083: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 084: internal class MonoLimitationAttribute : MonoTODOAttribute { 085: 086: public MonoLimitationAttribute (string comment) 087: : base (comment) 088: { 089: } 090: } 091: 092: [AttributeUsage (AttributeTargets.All, AllowMultiple=true)] 093: internal class MonoNotSupportedAttribute : MonoTODOAttribute { 094: 095: public MonoNotSupportedAttribute (string comment) 096: : base (comment) 097: { 098: } 099: } 100: }
上述 C# 源程序中共定义了 System 命名空间中的六个 internal 类:
- MonoTODOAttribute: internal class,派生自 Attribute 类,是以下五个类的基类。
- MonoDocumentationNoteAttribute: internal class
- MonoExtensionAttribute: internal class
- MonoInternalNoteAttribute: internal class
- MonoLimitationAttribute: internal class
- MonoNotSupportedAttribute: internal class
这六个类都是直接或间接地从 Attribute 类派生,因此它们都是特性,目的是将预定义的系统信息或用户定义的自定义信息与目标元素相关联。目标元素可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性、返回值、结构或其他特性。AttributeTargets.All 指明它们可以作用于所有上述目标元素。AllowMultiple=true 指明它们每一个都可以在同一目标元素上多次使用(可以携带不同的以字符串表示的信息)。MonoTODOAttribute 类有两个构造函数,分别是无参数的构造函数和需要一个字符串参数的构造函数。而其余五个类非常相似,都只有需要一个字符串参数的构造函数。
在 Console.dll 这个项目中,MonoTODO 特性在 TermInfoDriver.cs 中被使用过一次,MonoLimitation 特性在 Console.cs 中被使用过十一次。其他四个特性没有在这个项目中使用。
另外,把这六个类分别放在六个不同的 .cs 文件中会不会更好一点?
ControlCharacters 类 (internal class)
下面就是 mcs/class/corlib/System/ControlCharacters.cs:
01: // 02: // System.TermInfoBooleans 03: // 04: // Authors: 05: // Gonzalo Paniagua Javier (gonzalo@ximian.com) 06: // 07: // (C) 2009 Novell, Inc (http://www.novell.com) 08: // 09: 10: // 11: // Permission is hereby granted, free of charge, to any person obtaining 12: // a copy of this software and associated documentation files (the 13: // "Software"), to deal in the Software without restriction, including 14: // without limitation the rights to use, copy, modify, merge, publish, 15: // distribute, sublicense, and/or sell copies of the Software, and to 16: // permit persons to whom the Software is furnished to do so, subject to 17: // the following conditions: 18: // 19: // The above copyright notice and this permission notice shall be 20: // included in all copies or substantial portions of the Software. 21: // 22: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29: // 30: // These values are taken from 'man 5 terminfo' and /usr/include/term.h. 31: // They are the indexes for the boolean capabilities in a terminfo file. 32: namespace System { 33: class ControlCharacters { 34: public const int Intr = 0; 35: public const int Quit = 1; 36: public const int Erase = 2; 37: public const int Kill = 3; 38: public const int EOF = 4; 39: public const int Time = 5; 40: public const int Min = 6; 41: public const int SWTC = 7; 42: public const int Start = 8; 43: public const int Stop = 9; 44: public const int Susp = 10; 45: public const int EOL = 11; 46: public const int Reprint = 12; 47: public const int Discard = 13; 48: public const int WErase = 14; 49: public const int LNext = 15; 50: public const int EOL2 = 16; 51: } 52: }
上述源程序的第 33 行虽然没有 internal 修饰符,但是根据 C# 语法,class 的默认修饰符就是 internal。另外,第 2 行的注释是“System.TermInfoBooleans”,这不正确,应该改为“System.ControlCharacters”。还有,如果在第 33 行加上 static 关键字,将该类声明为静态类更好一些。或者改为结构(struct)?这里不使用枚举(enum),是因为它们是要作为数组的下标使用。如果是枚举的话,在使用时还需要转换为 int 类型。
在 Console.dll 这个项目中,ControlCharacters 类只在 TermInfoDriver.cs 中被使用过两次。
ConsoleKeyInfo 结构 (public struct)
下面就是 mcs/class/corlib/System/ConsoleKeyInfo.cs:
001: // 002: // System.ConsoleKeyInfo.cs 003: // 004: // Authors: 005: // Gonzalo Paniagua Javier (gonzalo@ximian.com) 006: // 007: // (C) 2005 Novell, Inc (http://www.novell.com) 008: // 009: 010: // 011: // Permission is hereby granted, free of charge, to any person obtaining 012: // a copy of this software and associated documentation files (the 013: // "Software"), to deal in the Software without restriction, including 014: // without limitation the rights to use, copy, modify, merge, publish, 015: // distribute, sublicense, and/or sell copies of the Software, and to 016: // permit persons to whom the Software is furnished to do so, subject to 017: // the following conditions: 018: // 019: // The above copyright notice and this permission notice shall be 020: // included in all copies or substantial portions of the Software. 021: // 022: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 023: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 024: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 025: // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 026: // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 027: // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 028: // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 029: // 030: namespace System { 031: [Serializable] 032: public struct ConsoleKeyInfo { 033: internal static ConsoleKeyInfo Empty = new ConsoleKeyInfo ('\0', 0, false, false, false); 034: ConsoleKey key; 035: char keychar; 036: ConsoleModifiers modifiers; 037: 038: public ConsoleKeyInfo (char keyChar, ConsoleKey key, bool shift, bool alt, bool control) 039: { 040: this.key = key; 041: this.keychar = keyChar; 042: modifiers = 0; 043: SetModifiers (shift, alt, control); 044: } 045: 046: internal ConsoleKeyInfo (ConsoleKeyInfo other) 047: { 048: this.key = other.key; 049: this.keychar = other.keychar; 050: this.modifiers = other.modifiers; 051: } 052: 053: internal void SetKey (ConsoleKey key) 054: { 055: this.key = key; 056: } 057: 058: internal void SetKeyChar (char keyChar) 059: { 060: this.keychar = keyChar; 061: } 062: 063: internal void SetModifiers (bool shift, bool alt, bool control) 064: { 065: this.modifiers = (shift) ? ConsoleModifiers.Shift : 0; 066: this.modifiers |= (alt) ? ConsoleModifiers.Alt : 0; 067: this.modifiers |= (control) ? ConsoleModifiers.Control : 0; 068: } 069: 070: public ConsoleKey Key { 071: get { return key; } 072: } 073: 074: public char KeyChar { 075: get { return keychar; } 076: } 077: 078: public ConsoleModifiers Modifiers { 079: get { return modifiers; } 080: } 081: 082: public override bool Equals (object value) 083: { 084: if (!(value is ConsoleKeyInfo)) 085: return false; 086: return Equals ((ConsoleKeyInfo) value); 087: } 088: 089: public static bool operator == (ConsoleKeyInfo a, ConsoleKeyInfo b) 090: { 091: return a.Equals (b); 092: } 093: 094: public static bool operator != (ConsoleKeyInfo a, ConsoleKeyInfo b) 095: { 096: return !a.Equals (b); 097: } 098: 099: public bool Equals (ConsoleKeyInfo obj) 100: { 101: return key == obj.key && obj.keychar == keychar && obj.modifiers == modifiers; 102: } 103: 104: public override int GetHashCode () 105: { 106: return key.GetHashCode () ^ keychar.GetHashCode () ^ modifiers.GetHashCode (); 107: } 108: } 109: }
上述源程序定义了 ConsoleKeyInfo 结构,用于描述按下的控制台键,包括控制台键表示的字符以及 Shift、Alt 和 Ctrl 修改键的状态。它不应由用户创建,而是作为 Console.ReadKey 方法的响应返回给用户。
ConsoleKeyInfo 结构定义了以下实例字段:
- key: 类型为 ConsoleKey,用于描述按下的控制台键。(第 34 行)
- keychar: 类型为 char,指出控制台键表示的字符。(第 35 行)
- modifiers: 类型为 ConsoleModifiers,指示 Shift、Alt 和 Ctrl 修改键的状态。(第 36 行)
第 33 行定义了一个 internal 静态属性 Empty,用作 NullConsoleDriver 类的 ReadKey 方法的返回值。
第 46 行到第 51 行定义了一个 internal 的复制构造函数,用于 CStreamWriter 类的 WriteKey 方法中。
第 38 行到第 44 行定义了一个 public 的构造函数,用于 TermInfoDriver 和 WindowsConsoleDriver 类中。在该构造函数中,使用传入的参数给上述三个字段赋值。其实第 42 行的“modifiers = 0;”语句是多余的,因为接下来的第 43 行中调用的 SetModifiers 方法会正确地给 modifiers 字段赋值,用不着先把该字段清零。
第 46 行到第 68 行的三个 internal 的 SetXXX 方法分别给上述三个字段赋值。
第 70 行到第 80 行的三个 public 的属性分别获取上述三个字段的值。
第 89 行到第 97 行的两个方法重载了等于(==)和不等于(!=)运算符,仅是调用下述的 Equals 方法。
第 99 行到第 102 行的 Equals 方法现了强类型的相等性。
第 82 行到第 87 行的 Equals 方法重写了基类的 Equals 方法,在第 86 行调用了前述 Equals 方法。
第 104 行到第 107 行的 GetHashCode 方法重写了基类的 GetHashCode 方法,返回哈希码。
ConsoleKeyInfo 结构在 Console.dll 项目中广泛使用,Console.cs、ConsoleDriver.cs、CStreamReader.cs、CStreamWriter.cs、IConsoleDriver.cs、NullConsoleDriver.cs、TermInfoDriver.cs 和 WindowsConsoleDriver.cs 中都有使用 ConsoleKeyInfo 结构。
因为 NullConsoleDriver.cs 中使用了 ConsoleKeyInfo 结构的 internal 静态属性 Empty,CStreamWriter.cs 中使用了 ConsoleKeyInfo 结构的 internal 复制构造函数,所以在我们的 Cosnole.dll 项目中需要包含 ConsoleKeyInfo.cs。不然的话,作为 public 的结构,我们可以直接使用 mscorlib.dll 中的 ConsoleKeyInfo 结构。
(未完待续)