这个问题更多的是针对良好的设计实践,而不是异常和堆栈.我很抱歉一开始并不清楚.
我希望在C#中为我的类提供自己的例外.在Java中,以下概念是完全合法的,因此如果您有一些堆栈的具体实现,您可以实现一致的错误处理(或任何其他类型的类)
public interface IStack
{
bool IsEmpty();
int Pop();
void Push(int element);
int Size { get; set; }
int Top();
public class EmptyException : Exception
{
}
public class SomeOtherClass
{
}
}
Run Code Online (Sandbox Code Playgroud)
当然,在C#中我得到一个错误,说"接口不能声明类型"
确保只实现我的接口的具体类可以访问EmptyException等的最佳方法是什么?
谢谢
您不能在接口或枚举中声明嵌套的类,接口,结构或枚举声明.
嵌套接口,枚举,结构和类声明仅允许在struct或class中.
在同一名称空间中声明一个类.
[Serializable]
public class StackEmptyException :
InvalidOperationException
{
public StackEmptyException() :
base("Cannot pop an item from an empty stack")
{
}
public StackEmptyException(string message) :
base(message)
{
}
/// <summary>Used for serialization. Never forget it!</summary>
protected StackEmptyException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
base(info, context)
{
}
}
Run Code Online (Sandbox Code Playgroud)
在C#中,将每个异常类命名为XXXException是一个很好的约定.
由于从空堆栈弹出项目是无效的操作,因此我将使用InvalidOperationException作为基本异常类型.
您还可以使用几种基类型,例如ArgumentException,ArgumentNullException,InvalidOperationException,ApplicationException.我建议您至少使用简单的异常,而不是使用简单的异常,因此人们可以在catch中更好地过滤异常.
如果可以的话,首选使用已经在框架中声明的异常类型,有很多并且通常它们已经足够了,对于您的示例,我将直接使用InvalidOperationException而不编写新的异常.
我还建议你使它可序列化(添加[Serializable]属性并复制序列化构造函数)或者将来人们会责怪你"为什么这个人没有将他的异常序列化,为什么!".
java和C#关于异常的一个很大区别是,在C#中,每个方法都可以抛出异常,比如C++.您不必(也不能)指定方法可以抛出的异常.但是你可以添加评论......
/// <summary>Pop an item from the stack.</summary>
/// <returns>The element removed from the stack.</returns>
/// <exception cref="System.InvalidOperationException">Throws InvalidOperationException if stack is empty.</exception>
public object Pop() { ... }
Run Code Online (Sandbox Code Playgroud)
仅使代码引发异常的方法是将主构造函数声明为internal.在C#中,内部成员仅在声明它们的程序集中可见.因此,如果您正在编写库,则只需添加内部关键字即可.如果您仍希望保持序列化,则无法密封该类,但没有人能够在您的库外调用您的构造函数.
[Serializable]
public class StackEmptyException :
InvalidOperationException
{
// This constructor is internal, it means, only the assembly that contains this exception can throw it.
// In C# there is not the "friend" keyword like in C++ so we can just use internal.
internal StackEmptyException() :
base("Cannot pop an item from an empty stack")
{
}
/// <summary>Used for serialization. Never forget it!</summary>
protected StackEmptyException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
base(info, context)
{
}
}
Run Code Online (Sandbox Code Playgroud)
然而,没有办法在界面内声明"受保护"的东西,所以你的问题不能得到肯定的答案.接口中的方法,事件和属性都是公共的.
您可以使用抽象类,但当然,在C#(如java)中,您没有多重继承,因此可能对您没用.例外情况应该全部是公开的,或者没有人可以在你的课堂之外发现你的例外,这是一个糟糕的设计!
可能你试图强迫语言从设计的角度来执行一些不太好的东西.
例外必须是公开的..NET中的异常不是接口契约的一部分,只有属性方法和事件才是接口契约的一部分.
也许我在你的设计中遗漏了一些东西,但你不需要做任何特殊的事情来确保一个类"可以"抛出异常.任何类都可以随时抛出它想要的任何异常.唯一的要求是异常类是可见的.
确保异常与您的界面在同一个程序集和相同的命名空间中,你会没事的.
public interface IStack
{
bool IsEmpty();
int Pop();
void Push(int element);
int Size { get; set; }
int Top();
}
public class Empty : Exception
{
}
Run Code Online (Sandbox Code Playgroud)