3

好的,假设我在 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();

我的问题是,每当我尝试将integersanddoubles转换String为时,都会引发异常。

如果我在语句try/catch周围放置一个块foreach,则在第二次迭代中引发的异常将触发对异常的捕获,并且不会将任何内容写入我的文本文档。

将 try/catch 放在 foreach 中是没有意义的,因为异常发生在演员表上。

我想使用 foreach 循环(让我们假设 for 循环不存在,并且我们不能使用索引 or ToString())来枚举对象数组,将每个对象转换为字符串并使用StreamWriter. 如果演员工作,快乐的日子。如果没有,我想捕获抛出的异常并继续枚举剩余的对象。

谢谢

编辑:在有人说之前,这不是家庭作业!我正在尝试解决一个现实世界的问题。

4

4 回答 4

6

因为您期望异构集合,所以最好避免InvalidCastException首先抛出。阅读 Eric Lippert 出色的Vexing exceptions文章中的“愚蠢的异常” 。

选项 1:使用 LINQOfType<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等。在这种情况下,你应该让进程死掉。
于 2012-05-20T13:41:24.077 回答
0

您不需要将对象投射到自己的字符串中。StreamWriter 有一个重载,它接受对象并自动进行强制转换(MSDN 链接):

foreach (object myObject in myObjects)
{
    sw.WriteLine(myObject);
}
于 2012-05-20T13:56:10.663 回答
0

你不能抓住并继续吗?

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();
于 2012-05-20T14:08:34.493 回答
0

好的。我知道这个问题已经回答了。但我觉得这很有趣。如果您想真正掌握foreach循环中抛出的所有异常,您可以将其存储为 Exception 类型的通用列表,稍后您可以将其作为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;
        }   
于 2012-05-20T15:08:33.510 回答