接口无法声明类型问题C# [英] Interfaces Cannot Declare Type Issue C#

查看:264
本文介绍了接口无法声明类型问题C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题更多的是针对良好的设计实践,而不是异常和堆栈。我很抱歉一开始并不清楚。



我想在C#中为我的课程设置自己的异常。在Java中,以下概念是完全合法的,因此如果您有一些堆栈的具体实现,您可以实现一致的错误处理(或任何其他类型的类)

 公共接口IStack 
{
bool IsEmpty();
int Pop();
void Push(int element);
int Size {get;组; }
int Top();

公共类EmptyException:异常
{
}

公共类SomeOtherClass
{
}
}

当然,在C#中我得到一个错误,说接口不能声明类型



确保只实现我的界面的具体类可以访问EmptyException等的最佳方法是什么?



谢谢

解决方案

您不能在接口或枚举中声明嵌套的类,接口,结构或枚举声明。



只允许在struct或class中使用嵌套接口,枚举,结构和类声明。



在同一名称空间中声明一个类。

  [Serializable] 
public class StackEmptyException:
InvalidOperationException
{
public StackEmptyException():
base(无法从空堆栈弹出项目)
{
}

public StackEmptyException(string message):
base(message)
{
}

/ //< summary>用于序列化。别忘了!< / 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]属性并复制序列化构造函数)或者将来人们会责怪你为什么这个人没有将他的异常序列化,为什么!。



java和C#之间关于异常的一个重要区别是,在C#中,每个方法都可以抛出异常,比如C ++。您不必(也不能)指定方法可以抛出的异常。
然而,您可以添加评论...

  ///< summary>从堆栈中弹出一个项目< /总结> 
///< returns>从堆栈中删除的元素。< / returns>
///< exception cref =System.InvalidOperationException>如果stack为空,则抛出InvalidOperationException。< / exception>
公共对象Pop(){...}

一种只生成代码的方法提出异常是将主构造函数声明为internal。
在C#中,内部成员仅在声明它们的程序集中可见。
因此,如果您正在编写库,则只需添加内部关键字即可。
如果你想让它保持序列化,你不能密封课程,但是没有人可以在你的图书馆外调用你的构造函数。

  [Serializable] 
公共类StackEmptyException:
InvalidOperationException
{
//这个构造函数是内部的,这意味着,只有包含此异常的程序集才能丢它。
//在C#中没有像C ++那样的friend关键字,所以我们可以使用内部。
internal StackEmptyException():
base(无法从空堆栈弹出项目)
{
}

///< summary> ;用于序列化。别忘了!< / summary>
protected StackEmptyException(System.Runtime.Serialization.SerializationInfo info,System.Runtime.Serialization.StreamingContext context):
base(info,context)
{
}
}

但是没有办法在界面内声明受保护的东西,所以你的问题不能有一个肯定的答案。
接口中的方法,事件和属性都是公共的。



你可以使用抽象类,但当然,在C#中(如java)你没有多重继承,所以对你没用。
例外应该全部公开,但是,没有人可以在你的课堂外捕捉你的例外,这是一个糟糕的设计!



你可能正在尝试从设计的角度来强迫语言执行不太好的事情。



例外必须是公开的。
.NET中的异常不是接口契约的一部分,只有属性方法和事件才是接口契约的参与者。


This question is more aimed at good design practices rather than exceptions and stacks. My apologies for not being clear at first.

I want to play about with having my own exceptions for my classes in C#. In Java the following concept is perfectly legal so that if you have a few concrete implementations of a stack you can implement consistent error handling (or any other type of class)

public interface IStack
{   
    bool IsEmpty();
    int Pop();
    void Push(int element);
    int Size { get; set; }
    int Top();

    public class EmptyException : Exception
    {
    }

    public class SomeOtherClass
    {
    }
}  

Of course, in C# I get an error saying that 'Interfaces cannot declare types'

What is the best way to ensure only concrete classes that implement my interface can access EmptyException etc?

Thanks

解决方案

You cannot declare a nested class, interface, struct or enum declaration inside an interface or enum.

Nested interfaces, enums, struct and classes declarations are allowed only inside struct or class.

Declare a class in the same namespace.

    [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)
        {
        }
    }

In C# is a good convention to name every exception class as XXXException.

Since it is an invalid operation to pop an item from an empty stack, I would use InvalidOperationException as base exception type.

There are also several base types you can use, for example ArgumentException, ArgumentNullException, InvalidOperationException, ApplicationException. Instead of using the simple Exception I would suggest you to use at least ApplicationException, so people can filter your exceptions better in catch.

Is preferred that you use an exception type already declared in the framework if you can, there are a lot and usually they are enough, for your example I would have used directly InvalidOperationException without writing a new exception.

I also suggest you to make it serializable (add the [Serializable] attribute and copy serialization constructor) or in the future people will blame at you "why this guy didn't make his exception serializable, why!".

One big difference between java and C# about exception is that in C# every method can throw an exception, like C++. You don't have to (and you cannot) specify what exceptions a method can throw. You can however add a comment...

        /// <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() { ... }

A way to make only your code to raise your exception is to declare the main constructor as internal. In C# internal members are visible only in the assembly where they are declared. So if you are writing a library you can just add the internal keyword. You cannot seal the class if you want still to keep it serializable, but no-one will be able to call your constructor outside your library.

    [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)
        {
        }
    }

There is however not a way to declare a "protected" thing inside an interface, so your question cannot have a positive answer. Also methods, events and properties in interfaces are all public.

You can use an abstract class for this, but of course, in C# (like java) you don't have multi-inheritance so maybe is not useful to you. Exceptions should be all public, however, or no-one can catch your exception outside your class, and this is a bad design!

Probably you are trying to force the language to perform something that is not really good from a design point of view.

Exceptions must be public. Exceptions, in .NET, are not part of an interface contract, only properties method and events are parte of the interface contract.

这篇关于接口无法声明类型问题C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆