C# 试着抓住拦网。哪种解决方案更好
对我来说,这似乎是一个合理的模式:C# 试着抓住拦网。哪种解决方案更好,c#,design-patterns,try-catch,C#,Design Patterns,Try Catch,对我来说,这似乎是一个合理的模式: int.TryParse() 如果,而不是: int.Parse() 在try块内部。直到我在MS pattern&practices中找到这个示例 /// <summary> /// Update a setting value for our application. If the setting does not /// exist, then add the setting. /// </summa
int.TryParse()
如果,而不是:
int.Parse()
在try块内部。直到我在MS pattern&practices中找到这个示例
/// <summary>
/// Update a setting value for our application. If the setting does not
/// exist, then add the setting.
/// </summary>
/// <param name="Key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
try
{
// if new value is different, set the new value.
if (isolatedStore[Key] != value)
{
isolatedStore[Key] = value;
valueChanged = true;
}
}
catch (KeyNotFoundException)
{
isolatedStore.Add(Key, value);
valueChanged = true;
}
catch (ArgumentException)
{
isolatedStore.Add(Key, value);
valueChanged = true;
}
catch (Exception e)
{
Debug.WriteLine("Exception while using IsolatedStorageSettings: " + e.ToString());
}
return valueChanged;
}
使用Contains方法不是更好吗?另一方面,我读到CLR可以优化try-catch到simple-goto。我已经运行了测试,TryParse的运行速度比Parse快得多,因为.NET似乎花费了大量时间生成异常以在解析失败时抛出,但在TryParse中,它能够抛出一个false 我不确定哪一个更好,但我的测试表明,TryParse似乎更快,而且我认为TryParse比许多try/catch块具有更高的可读性
编辑:您的代码示例似乎与int解析没有任何关系。我已经运行了测试,TryParse的运行速度比Parse快得多,因为.NET似乎花费了大量时间生成异常以在解析失败时抛出,但在TryParse中它能够抛出一个false 我不确定哪一个更好,但我的测试表明,TryParse似乎更快,而且我认为TryParse比许多try/catch块具有更高的可读性
编辑:您的代码示例似乎与int解析无关。是的,不要为此使用catch块。我不知道你在哪里找到的代码,但我怀疑它非常古老。Contains方法要快得多。此外,请检查dictionary类的方法。是的,不要为此使用catch块。我不知道你在哪里找到的代码,但我怀疑它非常古老。Contains方法要快得多。此外,请查看dictionary类的方法。TryGetValue优于Contains,因为它避免了竞争条件。但是,如果您有多个线程访问字典,您将不得不以某种方式处理异常,尽管您可以最小化支付异常惩罚的次数。TryGetValue比Contains更好,因为它避免了竞争条件。但是,如果有多个线程访问字典,则必须以某种方式处理异常,尽管可以尽量减少支付异常惩罚的次数。我不确定isolatedStore应该是什么类型,但如果它是字典,则必须处理isolatedStore.TryGetValuekey,out值将是我首选的检查方式 对于赋值,除非key为null,否则isolatedStore[key]=value永远不应该抛出异常,这对调用方来说似乎是公平的。本质上,使用索引器本身就是一个添加或更新操作,尽管它不会告诉您以前是否存在该值 因此,是的,就像int.Parse vs int.TryParse一样,我们更喜欢提供响应的方法,比如TryGetValue,而不是至少在这样的可恢复情况下抛出异常的方法
Ben Voigt提出了一个关于线程安全的重要观点。使用TryGetValue并使用索引器isolatedStore[key]而不是.Add来分配值将消除任何异常,但操作仍然不是原子的。我不确定isolatedStore应该是什么类型,但如果它是字典,那么isolatedStore.TryGetValuekey,out值将是我首选的检查方法 对于赋值,除非key为null,否则isolatedStore[key]=value永远不应该抛出异常,这对调用方来说似乎是公平的。本质上,使用索引器本身就是一个添加或更新操作,尽管它不会告诉您以前是否存在该值 因此,是的,就像int.Parse vs int.TryParse一样,我们更喜欢提供响应的方法,比如TryGetValue,而不是至少在这样的可恢复情况下抛出异常的方法
Ben Voigt提出了一个关于线程安全的重要观点。使用TryGetValue并使用索引器isolatedStore[key]而不是.Add来分配该值将消除任何异常,但该操作仍然不是原子操作。我是否遗漏了什么?Parse和TryParse与较长的代码样本有什么关系?我认为他引用了Parse和TryParse实现的模式的差异;也就是说,抛出应该处理的异常,并使用bool来允许if测试。在他的代码示例中,您可以看到他们使用前一种方法来处理流控制,而不是使用isolatedStore.Contains和if语句来引导流。@Justin:问题是示例使用索引器引发的KeyNotFoundException,而不是使用Contains调用检查项是否存在。前者相当于int.Parse,后者相当于int.TryParse。OP想知道为什么要使用异常处理版本而不是try版本。示例代码会吞噬异常-不好。@Martin,如果异常处理程序完全处理异常,为什么要让它冒泡?或者你是裁判
是否转到记录异常的最后一个处理程序?我认为这两种情况都没有问题。虽然就我个人而言,我从未对控制流使用异常处理——只对真正的错误情况使用。我是否遗漏了什么?Parse和TryParse与较长的代码样本有什么关系?我认为他引用了Parse和TryParse实现的模式的差异;也就是说,抛出应该处理的异常,并使用bool来允许if测试。在他的代码示例中,您可以看到他们使用前一种方法来处理流控制,而不是使用isolatedStore.Contains和if语句来引导流。@Justin:问题是示例使用索引器引发的KeyNotFoundException,而不是使用Contains调用检查项是否存在。前者相当于int.Parse,后者相当于int.TryParse。OP想知道为什么要使用异常处理版本而不是try版本。示例代码会吞噬异常-不好。@Martin,如果异常处理程序完全处理异常,为什么要让它冒泡?或者您指的是他记录异常的最后一个处理程序?我认为这两种情况都没有问题。虽然就我个人而言,我从未对控制流使用异常处理——只在真正的错误情况下使用。字典不是天生的线程安全的,所以我不知道竞争条件是如何应用的。如果两个线程试图写入您的字典,而您没有锁定,那么您已经陷入了严重的麻烦。当然,如果写入操作需要锁定,读取操作也需要锁定,我的理解是TryGetValue更好,因为它只需要在字典中进行一次哈希查找,而不是一次查找包含操作,另一次查找值。只是锁定的粒度不同而已。不同类型的更好。更好的正确性是因为它更原子,更好的性能是因为它只是一个散列查找。字典不是天生的线程安全的,所以我不知道竞争条件是如何应用的。如果两个线程试图写入您的字典,而您没有锁定,那么您已经陷入了严重的麻烦。当然,如果写入操作需要锁定,读取操作也需要锁定,我的理解是TryGetValue更好,因为它只需要在字典中进行一次哈希查找,而不是一次查找包含操作,另一次查找值。只是锁定的粒度不同而已。不同类型的更好。更好的正确性是因为它更原子,更好的性能是因为它只有一个哈希查找。@Chris:谢谢@拉杰:谢谢你对格式的修改,通常我会做得更好。@Chris:谢谢@拉杰:谢谢你对格式的修改,通常我对这方面比较在行。事实并非如此。它是超级新的:设置样本它不是。这是全新的:设置样本