在虚拟函数中抛出异常是一种好习惯吗?

时间:2009-04-27 13:47:48

标签: c#

即使解决方案非常明显,我也不应该发布这个,我将其作为提醒和其他人的有用参考点。

我有以下基类:

using System;

namespace LibraryWPF
{
    public class Library
    {
        /// <summary>
        /// Event fired when content is added to the libary
        /// </summary>
        public event EventHandler<ObjectInfoEventArgs> Library_ObjectAdded;

        /// <summary>
        /// Event fired when the scan of the library is finished
        /// </summary>
        public event EventHandler Library_Finished;

        // Properties

        /// <summary>
        /// Whether to stop checking the library or not
        /// </summary>
        public bool Stop
        {
            get;
            set;
        }

        /// <summary>
        /// Where to look for content
        /// </summary>
        public string Root
        {
            get;
            set;
        }

        /// <summary>
        /// Empty instance of library's object for reflection
        /// </summary>
        public virtual object ObjectInfo
        {
            get
            {
                // Should this raise as exception to show if it's not been overridden?
                return null;
            }
        }

        /// <summary>
        /// Sub class overrides this method to call it's actual find code
        /// </summary>
        public virtual void Find()
        {
            // Should this raise as exception to show if it's not been overridden?
        }

        /// <summary>
        /// Build the library
        /// </summary>
        public void Build()
        {
            if (Root != null && Root.Length > 0)
            {
                Stop = false;
                Find();
            }

            // Final update
            if (Library_Finished != null)
            {
                Library_Finished(this, null);
            }
        }

        /// <summary>
        /// Sub class calls this method to fire the ObjectAdded event
        /// </summary>
        /// <param name="objectInfo">Object just added to library</param>
        protected void OnObjectAdded(object objectInfo)
        {
            if (Library_ObjectAdded != null)
            {
                Library_ObjectAdded(this, new ObjectInfoEventArgs(objectInfo));
            }
        }
    }
}

子类重写ObjectInfo以返回他们正在寻找反射使用的对象类型的实例。他们还会覆盖Find来进行实际搜索。

这样我的应用程序代码就可以使用基类方法,因此在编译时不必了解子类的任何信息。我告诉它使用DI寻找什么样的内容。

所以 - 我的问题是:

我是否应该在ObjectInfoFind的基类版本中抛出异常,这样如果子类没有正确实现,我会遇到运行时错误?或者我应该为ObjectInfo返回null编码吗?

5 个答案:

答案 0 :(得分:12)

如果您需要一个方法由派生类实现,为什么不将它变为抽象而不是虚拟?这将强制派生类实现该成员。如果他们不想或不能返回ObjectInfo,他们可以选择自己返回null。

答案 1 :(得分:4)

您应该将派生类的基类和方法声明为abstract。这完全避免了probem,因为编译器将检测不覆盖所有abstarct方法的派生类。

答案 2 :(得分:1)

我认为有些属性是可选的,你应该有一个属性:ObjectInfo和一个布尔“SupportObjectInfo”。

在这种情况下,您将ObjectInfo属性标记为虚拟并抛出NotSupportedException。

您这样做,因为您的类的使用者可以测试它是否支持该属性,并且不必捕获错误以进行测试。

如果在实现中它不是可选的,则应将其标记为抽象。

答案 3 :(得分:1)

如果您希望“保护”基类的调用者不接收从您的基类派生的类抛出的潜在意外异常,请考虑使用模板模式捕获派生类抛出的任何错误并将其转换为您在基类上定义的异常。您还应该考虑将派生类抛出的异常作为内部异常传递。

答案 4 :(得分:0)

您当然可以这样做,但异常通常表示执行时错误,而不是实现错误。