I am reading the CLR via C# book, the author shows how to define custom exception as:
class Program { static void Main(string[] args) { TestException(); } static void TestException() { try { throw new Exception<DiskFullExceptionArgs>(new DiskFullExceptionArgs(@"C:\"), "The disk is full"); } catch (Exception<DiskFullExceptionArgs> e) { Console.WriteLine(e.Message); } } } [Serializable] public sealed class DiskFullExceptionArgs : ExceptionArgs { private readonly String m_diskpath; // private field set at construction time public DiskFullExceptionArgs(String diskpath) { m_diskpath = diskpath; } public String DiskPath { get { return m_diskpath; } } // Override the Message property to include our field (if set) public override String Message { get { return (m_diskpath == null) ? base.Message : "DiskPath=" + m_diskpath; } } } [Serializable] public abstract class ExceptionArgs { public virtual String Message { get { return String.Empty; } } } [Serializable] public sealed class Exception<TExceptionArgs> : Exception, ISerializable where TExceptionArgs : ExceptionArgs { private const String c_args = "Args"; // For (de)serialization private readonly TExceptionArgs m_args; public TExceptionArgs Args { get { return m_args; } } public Exception(String message = null, Exception innerException = null) : this(null, message, innerException) { } public Exception(TExceptionArgs args, String message = null, Exception innerException = null) : base(message, innerException) { m_args = args; } // This constructor is for deserialization; since the class is sealed, the constructor is // private. If this class were not sealed, this constructor should be protected [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] private Exception(SerializationInfo info, StreamingContext context) : base(info, context) { m_args = (TExceptionArgs)info.GetValue(c_args, typeof(TExceptionArgs)); } // This method is for serialization; it's public because of the ISerializable interface [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(c_args, m_args); base.GetObjectData(info, context); } public override String Message { get { String baseMsg = base.Message; return (m_args == null) ? baseMsg : baseMsg + " (" + m_args.Message + ")"; } } public override Boolean Equals(Object obj) { Exception<TExceptionArgs> other = obj as Exception<TExceptionArgs>; if (other == null) return false; return Object.Equals(m_args, other.m_args) && base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } }
I have two questions:
Q1-Whats the benefit to define a custom exception args ExceptionArgs
and create a concrete DiskFullExceptionArgs
? From my understanding, you can just pass a whole message "The disk is full C:" to the custom exception, why separate "C:" into ExceptionArgs
and "The disk is full" to the custom exception?
Q2- This custom exception overwrite Equals
methods. But why you need to compare two Exception instance? I don't see any scenarios that requires to compare two exception instances
没有评论:
发表评论