簡體   English   中英

接口無法聲明類型問題C#

[英]Interfaces Cannot Declare Type Issue C#

這個問題更多的是針對良好的設計實踐,而不是異常和堆棧。 我很抱歉一開始並不清楚。

我希望在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等的最佳方法是什么?

謝謝

您不能在接口或枚舉中聲明嵌套的類,接口,結構或枚舉聲明。

嵌套接口,枚舉,結構和類聲明僅允許在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。 我建議您至少使用簡單的異常,而不是使用簡單的異常,因此人們可以在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() { ... }

僅使代碼引發異常的方法是將主構造函數聲明為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)
        {
        }
    }

然而,沒有辦法在界面內聲明“受保護”的東西,所以你的問題不能得到肯定的答案。 接口中的方法,事件和屬性都是公共的。

您可以使用抽象類,但當然,在C#(如java)中,您沒有多重繼承,因此可能對您沒用。 例外情況應該全部是公開的,或者沒有人可以在你的課堂之外發現你的例外,這是一個糟糕的設計!

可能你試圖強迫語言從設計的角度來執行一些不太好的東西。

例外必須是公開的。 .NET中的異常不是接口契約的一部分,只有屬性方法和事件才是接口契約的一部分。

也許我在你的設計中遺漏了一些東西,但你不需要做任何特殊的事情來確保一個類“可以”拋出異常。 任何類都可以隨時拋出它想要的任何異常。 唯一的要求是異常類是可見的。

確保異常與您的界面在同一個程序集和相同的命名空間中,你會沒事的。

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


public class Empty : Exception
{
}

只要實現接口的類在范圍內具有異常,它就可以拋出它。 我無法弄清楚你要在這里描述什么,你必須幫忙。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM