Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 正确使用.NET异常_C#_Exception - Fatal编程技术网

C# 正确使用.NET异常

C# 正确使用.NET异常,c#,exception,C#,Exception,以下实例中要抛出的正确异常是什么 例如,如果我有一个类:专辑,其中包含一组歌曲: List<Song> 如果用户试图添加已经存在的歌曲,我是否应该抛出异常?如果是,什么类型的例外 我听说过这样一句话:“仅在异常情况下使用异常”,但我想告诉客户机到底出了什么问题(而不仅仅是返回布尔值)。您始终可以创建自己的异常。只需创建一个继承自Exception(或者在本例中是ArgumentException)的类 类似于DuplicateItemException(或者DuplicateSon

以下实例中要抛出的正确异常是什么

例如,如果我有一个类:专辑,其中包含一组歌曲:

List<Song>
如果用户试图添加已经存在的歌曲,我是否应该抛出异常?如果是,什么类型的例外


我听说过这样一句话:“仅在异常情况下使用异常”,但我想告诉客户机到底出了什么问题(而不仅仅是返回布尔值)。

您始终可以创建自己的异常。只需创建一个继承自
Exception
(或者在本例中是
ArgumentException
)的类


类似于
DuplicateItemException
(或者
DuplicateSongException
,如果您想要非常具体的东西)的内容听起来是正确的。

如果您的用例暗示集合中的项应该是唯一的,那么您应该使用一个数据结构来实现这一点

通过这样做,不仅可以避免编写O(N)查找方法来检查重复项,还可以冒泡出这种类型的集合将引发的预先存在的重复键异常

然而,.NET并没有保留排序顺序的独特集合,尽管扩展列表以支持这一点非常容易

下面我使用的方法通过在第二个哈希集中存储唯一值来牺牲内存占用来提高速度。如果内存大小更重要,则只需对每个Add操作进行O(N)检查。因为方法在列表中不是虚拟的(出于某种原因),所以我使用new关键字隐藏了基本方法

请注意,这只是一个示例,不是线程安全的,可能不应在实际生产应用程序中使用

    public class UniqueList<T> : List<T>
    {
        private HashSet<T> _internalHash = new HashSet<T>();

        public UniqueList() : base() { }
        public UniqueList(IEnumerable<T> collection) : base(collection) { }
        public UniqueList(int capacity) : base(capacity) { }

        public new void Add(T item)
        {
            if (!_internalHash.Add(item))
                throw new ArgumentException("Item already exists in UniqueList");

            base.Add(item);
        }

        public new void AddRange(IEnumerable<T> collection)
        {
            foreach (T t in collection)
            {
               this.Add(t);
            }
        }

        public new bool Remove(T item)
        {
            _internalHash.Remove(item);
            return base.Remove(item);               
        }

        public new int RemoveAll(Predicate<T> match)
        {
            int removedElems = 0;

            foreach (T item in this)
            {
                if (match(item))
                {
                    this.Remove(item);
                    removedElems++;
                }
            }

            return removedElems;
        }

        public new void RemoveAt(int index)
        {                
           this.Remove(this[index]);             
        }

        public new void RemoveRange(int index, int count)
        {
            for (int i = index; i < count; i++)
            {
                this.Remove(this[i]);
            }
        }
    }
公共类唯一列表:列表
{
私有HashSet_internalHash=新HashSet();
public UniqueList():base(){}
公共唯一列表(IEnumerable集合):基(集合){}
公共唯一列表(整数容量):基本(容量){}
新增公共作废(T项)
{
如果(!\u internalHash.Add(项目))
抛出新ArgumentException(“项目已存在于唯一列表中”);
基础。添加(项目);
}
public new void AddRange(IEnumerable集合)
{
foreach(集合中的T)
{
本条增补(t);
}
}
公共新bool删除(T项)
{
_删除(项目);
返回底座。移除(项目);
}
public new int RemoveAll(谓词匹配)
{
int-removedElems=0;
foreach(本文件中的T项)
{
如果(匹配(项目))
{
此项。删除(项目);
removedElems++;
}
}
返回移除元素;
}
公共新空移除(内部索引)
{                
删除(此[索引]);
}
公共新无效删除范围(整数索引、整数计数)
{
for(int i=索引;i
如果歌曲添加成功,AddSong方法可以返回布尔值-true,否则返回false,而不是抛出异常。就个人而言,我认为在这种情况下抛出一个例外是可以接受的,如果有理由认为这首歌在收藏中是独一无二的。例如,如果唱片集是唱片集上的歌曲列表,则您不需要重复歌曲(相同的标题、相同的持续时间、在曲目序列中的相同位置等)。您可以选择创建自己的从System.exception派生的异常类。exception可创建自定义错误(如果需要),这样您就可以抛出一个异常,准确解释错误发生的原因。

如果要提供有用的异常,您可能需要一个基本异常

AlbumException

然后根据CMerat的答案创建

DuplicateSongException

这当然应该继承自
AlbumException


就我个人而言,我会使Album类不可变。在这种情况下,整个局面就会消失

在完全相同的情况下,微软的.NET设计人员向我们发送了一条描述性消息。哦,还有。

他们可能应该使用
HashSet
,然后如果
Add
返回false,他们可以抛出一个异常。@混乱:一个集合不是有序的。@Johannes-Yep,在MSDN上验证过。我想我以前从来没有真正需要关心这个事实。嗯,总是有分类词典。就我个人而言,我会使Album类不可变。在这种情况下,整个局面就会消失。
    public class UniqueList<T> : List<T>
    {
        private HashSet<T> _internalHash = new HashSet<T>();

        public UniqueList() : base() { }
        public UniqueList(IEnumerable<T> collection) : base(collection) { }
        public UniqueList(int capacity) : base(capacity) { }

        public new void Add(T item)
        {
            if (!_internalHash.Add(item))
                throw new ArgumentException("Item already exists in UniqueList");

            base.Add(item);
        }

        public new void AddRange(IEnumerable<T> collection)
        {
            foreach (T t in collection)
            {
               this.Add(t);
            }
        }

        public new bool Remove(T item)
        {
            _internalHash.Remove(item);
            return base.Remove(item);               
        }

        public new int RemoveAll(Predicate<T> match)
        {
            int removedElems = 0;

            foreach (T item in this)
            {
                if (match(item))
                {
                    this.Remove(item);
                    removedElems++;
                }
            }

            return removedElems;
        }

        public new void RemoveAt(int index)
        {                
           this.Remove(this[index]);             
        }

        public new void RemoveRange(int index, int count)
        {
            for (int i = index; i < count; i++)
            {
                this.Remove(this[i]);
            }
        }
    }