处理 foreach 语句中的强制转换异常
本文关键字:转换 异常 foreach 语句 处理 | 更新日期: 2023-09-27 18:34:56
好吧,假设我在 C# .Net 中有一个对象数组,如下所示:
object[] myObjects = new object[9];
myObjects[0] = "Foo";
myObjects[1] = 3;
myObjects[2] = 2.75;
myObjects[3] = "Bar";
myObjects[4] = 675;
myObjects[5] = "FooBar";
myObjects[6] = 12;
myObjects[7] = 11;
myObjects[8] = "FooBarFooBar";
我想在foreach块中枚举此数组并使用StreamWriter将每个字符串写入文本文档,如下所示:
StreamWriter sw = new StreamWriter(@"C:'z'foobar.txt");
foreach(string myObject in myObjects)
{
sw.WriteLine(myObject);
}
sw.Flush();
sw.Close();
我的问题是,每当我尝试将integers
和doubles
转换为String
时,都会抛出异常。
如果我在 foreach
语句周围放置一个try/catch
块,则在第二次迭代时引发的异常将触发异常的捕获,并且不会将任何内容写入我的文本文档。
将尝试/捕获放在foreach中是没有意义的,因为异常发生在演员表上。
我想使用 foreach 循环(假设 for 循环不存在,我们不能使用索引或 ToString()
(来枚举对象数组,将每个对象转换为字符串并使用 StreamWriter
将它们写入文本文档。如果演员阵容有效,快乐的日子。如果没有,我想捕获引发的异常并继续枚举其余对象。
谢谢
编辑:在有人说之前,这不是家庭作业!我正在尝试解决一个现实世界的问题。
因为您希望有一个异构集合,所以最好首先避免抛出InvalidCastException
。阅读 Eric Lippert 出色的 Vexing 异常文章中的"愚蠢的例外"。
选项 1:使用 LINQ OfType<TResult>()
扩展方法仅选取指定类型的元素:
// using System.Linq;
foreach(string myObject in myObjects.OfType<string>())
{
sw.WriteLine(myObject);
}
选项 2:自己进行类型检查:
foreach(object myObject in myObjects)
{
string s = myObject as string;
if (s != null)
sw.WriteLine(s);
}
此选项易于扩展以处理多种类型。
更新:
好的,但是如果在某些古怪的情况下,仍然在此行上抛出异常,会发生什么。有没有办法处理异常,然后继续我的枚举?
以下是在foreach
行上抛出异常的其他方式,您无法明智地处理这些方法:
-
myObjects.GetEnumerator()
引发异常。在这种情况下,根本无法启动枚举。 -
IEnumerator<string>.MoveNext()
会引发异常。在这种情况下,枚举器可能已损坏,并且枚举无法继续。 - 发生其他类型的致命异常:
OutOfMemoryException
、StackOverflowException
等。在这种情况下,您应该让该过程死亡。
你不需要强制转换对象来串你自己。StreamWriter 有一个重载,它接受对象并自动执行强制转换(MSDN 链接(:
foreach (object myObject in myObjects)
{
sw.WriteLine(myObject);
}
你不能抓住并继续吗?
StreamWriter sw = new StreamWriter(@"C:'z'foobar.txt");
foreach(string myObject in myObjects)
{
try
{
sw.WriteLine(myObject);
}
catch (Exception ex)
{
// process exception here
continue;
}
}
sw.Flush();
sw.Close();
好的。我知道这个问题已经得到了回答。但我认为这很有趣。如果你想真正掌握foreach
循环中抛出的所有异常,你可以将其存储为异常类型的泛型列表,稍后你可以把它作为一个AggregateException
博客文章和此 MSDN 链接中的详细信息
这是我与您的场景相对应的实现(这将捕获 foreach 循环中抛出的所有异常,并且在对象数组完全循环之前循环仍然不会中断(
try
{
List<Exception> exceptions = null;
foreach (object myObject in myObjects)
{
try
{
string str = (string)myObject;
if (str != null)
{
sw.WriteLine(str);
}
}
catch (Exception ex)
{
if (exceptions == null)
exceptions = new List<Exception>();
exceptions.Add(ex);
}
}
if (exceptions != null)
throw new AggregateException(exceptions);
}
catch(AggregateException ae)
{
//Do whatever you want with the exception or throw it
throw ae;
}