这个问题更多的是针对良好的设计实践,而不是异常和堆栈。我很抱歉一开始并不清楚。
我想在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
{
}
}
当然,在C#中我得到一个错误,说“接口不能声明类型”
确保只实现我的接口的具体类可以访问EmptyException等的最佳方法是什么?
由于
答案 0 :(得分:7)
您不能在接口或枚举中声明嵌套的类,接口,结构或枚举声明。
只允许在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)
{
}
}
在C#中,将每个异常类命名为XXXException是一个很好的约定。
由于从空堆栈弹出项目是无效操作,因此我将使用InvalidOperationException作为基本异常类型。
您还可以使用几种基类型,例如ArgumentException,ArgumentNullException,InvalidOperationException,ApplicationException。 我建议你至少使用简单的异常,而不是使用简单的异常,因此人们可以更好地过滤你的异常。
如果可以的话,首选使用已经在框架中声明的异常类型,有很多并且通常它们已经足够了,对于您的示例,我将直接使用InvalidOperationException而不编写新的异常。
我还建议你使它可序列化(添加[Serializable]属性并复制序列化构造函数)或者将来人们会责怪你&#34;为什么这个人没有将他的异常序列化,为什么!&#34;
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() { ... }
仅使代码引发异常的方法是将主构造函数声明为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)
{
}
}
然而,没有办法宣布一个&#34;受保护的&#34;界面内的东西,所以你的问题不能得到肯定的答案。 接口中的方法,事件和属性都是公共的。
你可以使用一个抽象类,但当然,在C#(比如java)中你不具备多重继承,所以对你没用。 例外情况应该是全部公开的,或者没有人可以在你的课堂之外发现你的例外,这是一个糟糕的设计!
可能你试图从设计的角度强迫语言执行一些不太好的东西。
例外必须是公开的。 .NET中的异常不是接口契约的一部分,只有属性方法和事件才是接口契约的参与者。
答案 1 :(得分:6)
也许我在你的设计中遗漏了一些东西但是,你不需要做任何特殊的事情来确保一个类“可以”抛出异常。任何类都可以随时抛出它想要的任何异常。唯一的要求是异常类是可见的。
确保异常与您的界面在同一个程序集和相同的命名空间中,你会没事的。
public interface IStack
{
bool IsEmpty();
int Pop();
void Push(int element);
int Size { get; set; }
int Top();
}
public class Empty : Exception
{
}
答案 2 :(得分:0)
只要实现接口的类在范围内有异常,它就可以抛出它。我无法弄清楚你要在这里描述什么,你必须帮忙。