1

次の方法は、使い捨てオブジェクトを反復処理する安全な方法ですか?それとも、これは無気力なオブジェクトになりますか?等?ネストを使用する代わりにdisposeステートメントを使用した場合はどうなりますか?

public static void Main()
{
   foreach (ChildObject oChild in webApp)
   {
        //On Noes!  Unexpected Error!
   }
}

public static IEnumerable<ChildObject> SafelyGetNextObjInWebApp(WebApplication webApp)
{
    foreach (ParentObject oParent in webApp.Parents)
    {
        using (parent)
        {
            foreach (ChildObject oChild in oParent.Children)
            {
                using (oChild)
                {
                    yield return oChild;
                }
            }
        }
    }
}
4

4 に答える 4

4

呼び出し元がによって返されるすべてのオブジェクトを列挙しない限り、メソッドは安全ではありませんSafelyGetNextObjInWebApp()。次のステートメントで何が起こるかを考えてみましょう。

ChildObject o = SafelyGetNextObjInWebApp(arg).First();

この場合、の実行はステートメントでSafelyGetNextObjInWebApp()停止し、yield続行されません。したがって、オブジェクトはこの呼び出しによって破棄されません。

イテレータを使用してWebサービスで作成されたオブジェクトを一度に1つずつ返す場合は、呼び出しが例外安全であることを確認し、イテレータ呼び出しの呼び出し元が破棄するように強制する必要があります。説明する:

public IEnumerable<ParentObject> GetParents(WebApplication webApp)
{
    // assumes webApp.Parents uses deferred execution.
    return webApp.Parents;
}

public void ProcessParent(WebApplication webApp)
{
    foreach (ParentObject p in GetParents())
    {
        // Assumes p.Dipsose() calls ChildObject.Dispose() for all p.ChildObjects.
        using(p)
        {
            foreach (ChildObject o in p.ChildObjects)
            {
                // do something with o
            }
        }
    }
}

}

于 2012-08-22T17:08:08.043 に答える
3

「安全な」方法は、結局のところそれほど安全ではないかもしれません。すべての親オブジェクトと子オブジェクトが反復される前に反復が中断(または失敗)した場合はどうなりますか?残りのオブジェクトは破棄されません(少なくとも、その特定のメソッドでは破棄されません)。

反復と廃棄は別々に保つ必要があるようです。よりクリーンなコードが得られ、プログラムの実行内容をより細かく制御できます。

そしてもっとあります...

C#イテレータパターンは、「安全な」メソッドを微妙に失敗させます。子オブジェクトを作成yieldすると、プログラムはブロックを効果的に「終了」しusing {...}、子を破棄して、反復から取得したユーザーが使用できなくなるようにしますSafelyGetNextObjInWebApp()

何ができるか

からusingステートメントを取り出しSafelyGetNextObjInWebApp()ます。生成された子オブジェクトを、子をいつ破棄するかを「認識」する「作業単位」クラスにカプセル化します。

于 2012-08-22T17:06:34.980 に答える
1

ブロックの最後でdisposeを実行するので、関数の最後でdisposeを使用するか使用するかで同じ結果になります

于 2012-08-22T17:03:39.723 に答える
1

コードは問題ないかもしれませんが、通常の使用では問題が発生する可能性があります。次の反復で破棄されるオブジェクトを返します。したがって、発信者のコードが次のようになっている場合

foreach(var i in SafelyGetNextObjInWebApp())
{
   if (IsInteresting(i))
   { 
     interestingItems.Add(i);
   }
}
// here interestingItems contains disposed items you can't use.

すべてのアイテムを繰り返し、引数として取るメソッドを提供することによってコードを逆にするとAction<T>、各アイテムの処理がアクション内で終了する必要があるという事実が浮き彫りになる可能性があります。

于 2012-08-22T17:28:14.517 に答える