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();

私の問題は、とをキャストしようとintegersするdoublesString、例外がスローされることです。

try/catchステートメントの周りにブロックを配置するforeachと、2回目の反復でスローされる例外が例外のキャッチをトリガーし、テキストドキュメントに何も書き込まれません。

キャストで例外が発生するため、foreach内にtry/catchを配置しても意味がありません。

foreachループを使用して(forループが存在せず、インデックス付けまたはを使用できないと仮定しますToString())、オブジェクトの配列を列挙し、それぞれを文字列にキャストし、を使用してテキストドキュメントに書き込みますStreamWriter。キャストがうまくいけば、幸せな日々。そうでない場合は、スローされた例外をキャッチし、残りのオブジェクトを列挙し続けます。

ありがとう

編集:誰かがそれを言う前に、これは宿題ではありません!私は現実世界の問題を解決しようとしています。

4

4 に答える 4

6

異種のコレクションを期待するため、InvalidCastExceptionそもそもスローを避けることをお勧めします。EricLippertの優れたVexing例外の記事で「骨の折れる例外」を読んでください。

オプション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()例外をスローします。この場合、列挙子が破損している可能性があり、列挙を続行できません。
  • 他のタイプの致命的な例外が発生します:OutOfMemoryExceptionStackOverflowExceptionなど。この場合、プロセスを停止させる必要があります。
于 2012-05-20T13:41:24.077 に答える
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 に答える
0

自分で文字列を作成するためにオブジェクトをキャストする必要はありません。StreamWriterには、オブジェクトを取得してキャストを自動的に実行するオーバーロードがあります(MSDNリンク)。

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