2

匿名方式の醜いことと利点を説明するように頼まれました。

たぶん説明しました

醜いこと

anonymous methods turning quickly into spaghetti code.

利点

匿名メソッドを使用してスレッドセーフなコードを生成できます:例

static List<string> Names = new List<string>(
  new string[] {
    "Jon Skeet",
    "Marc Gravell",
    "David",
    "Bill  Gates"
  });

static List<string> FindNamesStartingWith(string startingText)
{
  return Names.FindAll(
    delegate(string name)
    {
      return name.StartsWith(startingText);
    });
}

しかし、本当にスレッドセーフかどうかはわかりませんでした。正当化するように求められました。(1)匿名メソッドの利点(2)上記のコードスレッドは安全かどうかを理解するのに役立つ人 はいますか?

4

2 に答える 2

7

まあ、「スレッドセーフ」はかなり広い用語です。どのようなマルチスレッドの使用を考えていますか? リストに何も書き込まれていない場合、データの破損や例外なく安全であると期待しています...

さて、匿名メソッドの「醜さ」については... C# 3 を使用していますか? その場合は、ラムダ式の使用を開始してください。これは一般的にクリーンです。

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.FindAll(name => name.StartsWith(startingText));
}

または、LINQ を使用します。

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText)).ToList();
}

または、必ずしもリストが必要ない場合:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText));
}

または、クエリ式を使用する場合:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return from name in names
           where name.StartsWith(startingText)
           select name;
}

これらのどれも、私にはスパゲッティ コードのようには見えません。ただし、これを使用する必要があるのか​​、それとも別のものを使用する必要があるのか​​ を尋ねる場合は、実際に代替案を提示する必要があります. ここに簡単なものがあります:

static List<string> FindNamesStartingWith(string startingText)
{
    List<string> ret = new List<string>();
    foreach (string name in Names)
    {
        if (name.StartsWith(startingText))
        {
            ret.Add(name);
        }
    }
    return ret;
}

あなたはそれがより明確だと思いますか?もしそうなら、それでいいのですが、あなたが無名関数やLINQなどにあまり詳しくないだけだと思います。ご覧のとおり、かなり多くのコードがあります。以前のサンプルのいずれか。

于 2010-03-26T19:35:03.120 に答える
2

まあ、それはすべて、スレッドセーフの意味に依存します。

の実行中にFindAll他のスレッドが基になるNamesコレクションを変更すると、奇妙な結果が生じる可能性があります。

複数のスレッドでのへの複数の呼び出しFindAllは、それ自体で安全ですか? はい、それは間違いなくイエスです。

匿名メソッドの利点については、別の方法を検討してください。

あなたはしたい:

  1. コレクションのアイテムを見つける
  2. どのアイテムを見つけたいかを知る唯一の方法は、それぞれの式を評価することです

次のようにできます。

List<string> result = new List<string>();
foreach (string name in Names)
    if (name.StartsWith(startingText))
        result.Add(name);
return result;

または、新しいラムダ構文が与えられた場合、次のようにすることもできます。

return Names.FindAll(name => name.StartsWith(startingText));

どちらが好きかはわかっていますが、異なることを行い、結果は同じです (この場合)。

最初のケースでは、すべてのコードを自分で実行します。魔法はありません。

2 番目のケースでは、FindAllどの項目を結果に入れるかを決定する方法を与えます。この場合、それを行うための実行不可能な方法はありませんFindAll。アイテムごとに、指定したコードを実行する必要があります。

于 2010-03-26T19:37:36.850 に答える