RFC:异常和控制流程 [英] RFC: Exceptions and control flow

查看:180
本文介绍了RFC:异常和控制流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不得使用例外来控制程序流程。我打算表明

这个陈述是有缺陷的。


在某些情况下,可以用异常来控制程序流程

可以提高代码的可读性和性能。


考虑一个必须消除列表中重复项的应用程序。


使用系统。收藏;


// SETUP CODE使用System.Collections初始化一个列表并提供一个重复的

;

ArrayList arr = new ArrayList(10);

for(int i = 0; i< 10; i ++)

arr.Add(i.ToString());


// dupes

arr.Add(1.ToString());

//控制程序流程的异常从这里开始
Hashtable ht = new Hashtable();

foreach(新的ArrayList(arr)中的字符串str)

{

尝试

{

ht.Add(str,str);

}

catch(ArgumentException)

{

arr.Remove(str);

}

}

alg orithm实际上使用哈希表的唯一约束来实现唯一性。从逻辑上讲,程序流程由

存在异常控制。

这种方法在

中存在最小到中等重复时效果很好名单。与其他当代

技术相比,逻辑也清晰简洁且非常有效,可以删除列表中的重复项,通常涉及

重复和迭代列表的副本。


结论:不能使用异常来控制

程序流程。


评论/查询/接受者欢迎。


-

问候,

Alvin Bruney [微软MVP ASP.NET]


[无耻的作者插件]

带有.NET的Microsoft Office Web Components黑皮书

现已推出@ http://www.lulu.com/owc

------------------------------------------------- ---------

Exceptions must not be used to control program flow. I intend to show that
this statement is flawed.

In some instances, exceptions may be used to control program flow in ways
that can lead to improved code readability and performance.

Consider an application that must eliminate duplicates in a list.

using system.collections;

//SETUP CODE initialize a list and provide a duplicate
using System.Collections;
ArrayList arr = new ArrayList(10);
for(int i = 0; i < 10;i++)
arr.Add(i.ToString());

//dupes
arr.Add(1.ToString());
//Exception to control program flow starts here
Hashtable ht = new Hashtable();
foreach(string str in new ArrayList(arr))
{
try
{
ht.Add(str, str);
}
catch(ArgumentException)
{
arr.Remove(str);
}
}
The algorithm essentially uses the unique constrains of the hashtable to
enforce uniqueness. Logically, the program flow is controlled by the
presence of exceptions.
This approach works well when there are minimal to moderate duplicates in
the list. The logic is also clear and concise and very efficient compared
with other contemporary
techniques to remove duplicates in a list which typically involve
duplicating and iterating a copy of the list.

Conclusion: It is not true that exceptions must not be used to control
program flow.

comments/queries/takers welcome.

--
Regards,
Alvin Bruney [Microsoft MVP ASP.NET]

[Shameless Author plug]
The Microsoft Office Web Components Black Book with .NET
Now Available @ http://www.lulu.com/owc
----------------------------------------------------------

推荐答案

Alvin ...当代码工作时我违反了这个规则,效率很高

,易于阅读。但是,我认为不使用异常

来控制程序流的论点在某些内循环中是有效的,这导致了大量的展开。我怀疑你也可以使用hasttable.contains

来编写可读代码。


问候,

Jeff
Alvin... I have violated this rule when the code worked, was efficient
and easy to read. However, I believe the argument not to use exceptions
to control program flow is valid in certain inner loops that result in a
lot of unwinding. I suspect that you could also use hasttable.contains
to write readable code.

Regards,
Jeff
结论:不能使用异常来控制
Conclusion: It is not true that exceptions must not be used to control



程序流程。<


***通过开发人员指南 http://www.developersdex.com 发送***

不要只是参加USENET ......获得奖励!


program flow.<

*** Sent via Developersdex http://www.developersdex.com ***
Don''t just participate in USENET...get rewarded for it!


好吧,我从MS看过的所有内容都说明了提出错误的
大于测试

错误条件的性能,所以我认为测试你的例子会显示相同的

的事情。它并不总是成立:


在下面的代码中,我使用

try / catch和1000循环Alvin的代码1000次在添加到

HashTable之前测试dupe的次数。在几十个测试中,try / catch总是非常接近完成循环的2秒钟,而对于欺骗的测试非常接近于
10毫秒。在这种情况下,异常

的性能损失是非常大的。


然后我在1000演化循环之外移动了添加的欺骗 -

这样的错误条件只发生在1000次之上,而不是每次都是b $ b。在这种情况下,try / catch花费了大约5毫秒,并且对于欺骗的测试花费了相同的10毫秒。使用try / catch是更快的



当然,这些测试并不完全科学但差异很大

显着在短时间内以相对一致的方式重复几十次,我相信它们非常能代表真实的

世界,因为现实世界存在于我身上PC无论如何。


我的结论:


1.如果错误情况不太可能或者只会发生错误

非常小的百分比(在我的测试中为0.1%)的时间,try / catch可以比每次测试一个条件更快
,即使可能性为

现有条件非常低。


2.在所有其他情况下,错误条件甚至可能性为1%或者b
更大,那个例外有很大的性能打击。


DalePres

MCAD,MCDBA,MCSE


// SETUP CODE初始化列表并提供一个副本


ArrayList arr = new ArrayList(10);


for(int i = 0;我< 10; i ++)


arr.Add(i.ToString());


DateTime start;


DateTime结束;


start = DateTime.Now;


Console.WriteLine(start.ToString(&HH:mm) :ss.fff"));


for(int x = 0; x< 1000; x ++)


{


// dupes


arr.Add(1.ToString());


//异常从这里开始控制程序流程


Hashtable ht = new Hashtable();

foreach(新的ArrayList(arr)中的字符串str)


{


试试


{


ht.Add(str,str);


}


catch(ArgumentException)


{


arr.Remove(str);


}


}


}


end = DateTime.Now;


Console.WriteLine(end.ToString(" HH) :mm:ss.fff"));


start = DateTime.Now;


Co nsole.WriteLine(start.ToString(" HH:mm:ss.fff"));


for(int x = 0; x< 1000; x ++)


{


// dupes


arr.Add(1.ToString( ));


//控制程序流程的异常从这里开始


Hashtable ht = new Hashtable();


foreach(新的ArrayList(arr)中的字符串str)


{


if(ht [str] == null)


ht.Add(str,str);


else


arr。删除(str);


}


}


end = DateTime.Now;


Console.WriteLine(end.ToString(" HH:mm:ss.fff"));


Console.ReadLine();



" Alvin Bruney [MVP]" <蒸汽邮局的蒸汽>在消息中写道

新闻:Oo *************** @ TK2MSFTNGP09.phx.gbl ...
Well, everything I have seen from MS says that the performance hit in
raising an error is greater than the performance hit for testing for the
error condition so I thought that testing your example would show the same
thing. It did not always hold true:

In the code I list below, I looped Alvin''s code 1000 times using the
try/catch and 1000 times testing for the dupe before adding to the
HashTable. In a couple dozen tests, the try/catch always took very close to
2 seconds to complete the loop while testing for the dupe took very close to
10 milliseconds... In that case, the performance penalty of the exception
was very big.

Then I moved the addition of the dupe outside of the 1000 evolution loop -
that way the error condition only occurs once out of the 1000 times rather
than every time. In this case, the try/catch took about 5 milliseconds and
testing for the dupe took the same 10 milliseconds. Using the try/catch was
faster.

Granted, these tests are not exactly scientific but the differences were so
significant and repeated relatively consistently over dozens of times in a
short time period, I believe they''re pretty representative of the real
world, as the real world exists on my PC anyway.

My conclusion:

1. If the error condition is very unlikely or is going to happen only a
very tiny percentage (0.1% in my test) of the time, the try/catch can be
faster than testing for a condition every time, even when the likelihood of
that condition existing is very low.

2. In all other cases, where the error condition is even 1% likelihood or
greater, then the exception has a significant performance hit.

DalePres
MCAD, MCDBA, MCSE


//SETUP CODE initialize a list and provide a duplicate

ArrayList arr = new ArrayList(10);

for(int i = 0; i < 10;i++)

arr.Add(i.ToString());

DateTime start;

DateTime end;

start = DateTime.Now;

Console.WriteLine(start.ToString("HH:mm:ss.fff"));

for (int x = 0; x < 1000; x++)

{

//dupes

arr.Add(1.ToString());

//Exception to control program flow starts here

Hashtable ht = new Hashtable();

foreach(string str in new ArrayList(arr))

{

try

{

ht.Add(str, str);

}

catch(ArgumentException)

{

arr.Remove(str);

}

}

}

end = DateTime.Now;

Console.WriteLine(end.ToString("HH:mm:ss.fff"));

start = DateTime.Now;

Console.WriteLine(start.ToString("HH:mm:ss.fff"));

for (int x = 0; x < 1000; x++)

{

//dupes

arr.Add(1.ToString());

//Exception to control program flow starts here

Hashtable ht = new Hashtable();

foreach(string str in new ArrayList(arr))

{

if (ht[str] == null)

ht.Add(str, str);

else

arr.Remove(str);

}

}

end = DateTime.Now;

Console.WriteLine(end.ToString("HH:mm:ss.fff"));

Console.ReadLine();


"Alvin Bruney [MVP]" <vapor at steaming post office> wrote in message
news:Oo***************@TK2MSFTNGP09.phx.gbl...
例外不能是用于控制程序流程。我打算表明这个陈述是有缺陷的。

在某些情况下,异常可以用来控制程序流程,以便提高代码的可读性和性能。
Exceptions must not be used to control program flow. I intend to show that
this statement is flawed.

In some instances, exceptions may be used to control program flow in ways
that can lead to improved code readability and performance.



<" Alvin Bruney [MVP]" <蒸汽邮局的蒸汽>>写道:
<"Alvin Bruney [MVP]" <vapor at steaming post office>> wrote:
不得使用例外来控制程序流。我打算表明这个陈述是有缺陷的。

在某些情况下,异常可以用来控制程序流程,以便提高代码的可读性和性能。

考虑一个必须消除列表中重复项的应用程序。

使用system.collections;

// SETUP CODE初始化列表并提供一个复制
使用System.Collections;
ArrayList arr = new ArrayList(10);
for(int i = 0; i< 10; i ++)
arr.Add(i .ToString());

// dupes
arr.Add(1.ToString());

//控制程序流程的异常从这里开始
Hashtable ht = new Hashtable();
foreach(新的ArrayList(arr)中的字符串str)
{
尝试
{
ht.Add(str ,str);
}
catch(ArgumentException)
{
arr.Remove(str);
}
}


这比那更好:


foreach(新的ArrayList(arr)中的字符串str)

{

// H.我们之前见过这个吗?

if(ht.ContainsKey(str))

{

arr.Remove(str);

}

其他

{

ht [str] = str;

}

}


< snip>

结论:不能使用异常来控制程序流程。
Exceptions must not be used to control program flow. I intend to show that
this statement is flawed.

In some instances, exceptions may be used to control program flow in ways
that can lead to improved code readability and performance.

Consider an application that must eliminate duplicates in a list.

using system.collections;

//SETUP CODE initialize a list and provide a duplicate
using System.Collections;
ArrayList arr = new ArrayList(10);
for(int i = 0; i < 10;i++)
arr.Add(i.ToString());

//dupes
arr.Add(1.ToString());
//Exception to control program flow starts here
Hashtable ht = new Hashtable();
foreach(string str in new ArrayList(arr))
{
try
{
ht.Add(str, str);
}
catch(ArgumentException)
{
arr.Remove(str);
}
}
How is that better than:

foreach (string str in new ArrayList(arr))
{
// Have we seen this before?
if (ht.ContainsKey(str))
{
arr.Remove(str);
}
else
{
ht[str] = str;
}
}

<snip>
Conclusion: It is not true that exceptions must not be used to control
program flow.




我同意你的结论,但我不认为你的例子是一个特别好的例子。我反对这个规则的地方(和

总是感觉很糟糕,说实话)是我基本上需要的地方

跳到堆栈的几个级别。例如,测试很多

不同的东西:


尝试

{

TestFoo(1 ,2,3);

TestFoo(2,3,4);

TestBar();

TestFoo(5,6,7) );

返回true;

}

catch

{

返回false ;

}


如果测试失败,每个Test方法抛出一个异常

感觉不那么脆弱(和更清楚):


if(!TestFoo(1,2,3))

{

返回false;

}

if(!TestFoo(2,3,4))

{

返回false;

}

if(!TestBar())

{

返回false;

}

if(!TestFoo(5,6,7))

{

返回false;

}

返回true;


(不可否认,在这种情况下,它可以合理地减少为化合物

" if,但是现实生活中的代码测试线往往更复杂,

合并后会导致巨大且难以理解的测试。)


只有在测试方法* * * $ / b
时才适用虽然上面的目的 - 而且应该非常清楚

记录。


-

Jon Skeet - < sk ***@pobox.com>
http://www.pobox.com /〜双向飞碟

如果回复小组,请不要给我发邮件



I agree with your conclusion, but I don''t think your example is a
particularly good one. The places where I go against this rule (and
always feel bad doing it, to be honest) is where I basically need to
jump a couple of levels up the stack. For instance, testing lots of
different things:

try
{
TestFoo(1, 2, 3);
TestFoo(2, 3, 4);
TestBar();
TestFoo(5, 6, 7);
return true;
}
catch
{
return false;
}

where each of the Test methods throws an exception if the test fails
feels a lot less fragile (and clearer) than:

if (!TestFoo(1, 2, 3))
{
return false;
}
if (!TestFoo(2, 3, 4))
{
return false;
}
if (!TestBar())
{
return false;
}
if (!TestFoo(5, 6, 7))
{
return false;
}
return true;

(Admittedly in this case it could be reasonably reduced to a compound
"if", but in real life code the test lines are often more complicated,
leading to a huge and unreadable test when combined.)

This is only appropriate at all when the test methods are *solely*
there for the above purpose though - and that should be very clearly
documented.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


这篇关于RFC:异常和控制流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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