21 限制類型的可見性
不是每個類型都需要Public。你應給你的類型最少的可見度來達到你的目的,內部或私有類能實現公共的接口。很多獨立的類應當創建為內部的。你可以使用protected或私有嵌套類進一步來限制其可見性,可見性越小,當你之後更新時,整個系統的更改也就越少,越少的地方訪問你的代碼,你修改的地方也就越少。
只暴露那些需要暴露的。對於可見性小的類,嘗試使用公共接口來暴露。
// For illustration, not complete source public class List: IEnumerable { private class Enumerator : IEnumerator { // Contains specific implementation of // MoveNext(), Reset(), and Current. public Enumerator(List storage) { // elided } } public IEnumerator GetEnumerator() { return new Enumerator (this); } // other List members. }
public interface IPhoneValidator { bool ValidateNumber(PhoneNumber ph); } internal class USPhoneValidator : IPhoneValidator { public bool ValidateNumber(PhoneNumber ph) { // perform validation. // Check for valid area code, exchange. return true; } }
public static class Extensions { public static void ForAll( this IEnumerable sequence, Action action) { foreach (T item in sequence) action(item); } } // usage foo.ForAll((n) => Console.WriteLine(n.ToString()));
public struct URLInfo : IComparable, IComparable { private string URL; private string description; #region IComparable Members public int CompareTo(URLInfo other) { return URL.CompareTo(other.URL); } #endregion #region IComparable Members int IComparable.CompareTo(object obj) { if (obj is URLInfo) { URLInfo other = (URLInfo)obj; return CompareTo(other); } else throw new ArgumentException( "Compared object is not URLInfo"); } #endregion }
interface IMsg { void Message(); } public class MyClass : IMsg { public void Message() { Console.WriteLine("MyClass"); } }Message()方法現在是MyClass類的公共接口。Message也可以通過IMsg指針來訪問。現在我們來增加一個派生類:
public class MyDerivedClass : MyClass { public void Message() { Console.WriteLine("MyDerivedClass"); } }
public class MyClass : IMsg { public virtual void Message() { Console.WriteLine("MyClass"); } } public class MyDerivedClass : MyClass { public override void Message() { Console.WriteLine("MyDerivedClass"); } }
public class MyDerivedClass2 : MyClass { public sealed override void Message() { Console.WriteLine("MyDerivedClass"); } }
public class MyClass2 : IMsg { protected virtual void OnMessage() { } public void Message() { OnMessage(); Console.WriteLine("MyClass"); } }
public class DefaultMessageGenerator { public void Message() { Console.WriteLine("This is a default message"); } } public class AnotherMessageGenerator : DefaultMessageGenerator, IMsg { // No explicit Message() method needed. }
public class LoggerEventArgs : EventArgs { public string Message { get; private set; } public int Priority { get; private set; } public LoggerEventArgs(int p, string m) { Priority = p; Message = m; } } public class Logger { static Logger() { theOnly = new Logger(); } private Logger() { } private static Logger theOnly = null; public static Logger Singleton { get { return theOnly; } } // Define the event: public event EventHandlerLog; // add a message, and log it. public void AddMsg(int priority, string msg) { // This idiom discussed below. EventHandler l = Log; if (l != null) l(this, new LoggerEventArgs(priority, msg)); } }
class ConsoleLogger { static ConsoleLogger() { Logger.Singleton.Log += (sender, msg) => { Console.Error.WriteLine("{0}:\t{1}", msg.Priority.ToString(), msg.Message); }; } }