1. ホーム
  2. c#

[解決済み] 配列に一致する要素がない

2022-01-31 18:10:25

質問

私は、データ操作のためにlinqを使用しているasp.netアプリケーションを持っています。実行中に、例外 "Sequence contains no matching element" が発生しました。

if (_lstAcl.Documents.Count > 0)
{
    for (i = 0; i <= _lstAcl.Documents.Count - 1; i++)
    {
        string id = _lstAcl.Documents[i].ID.ToString();                           
        var documentRow = _dsACL.Documents.First(o => o.ID == id);
        if (documentRow !=null)
        {

            _lstAcl.Documents[i].Read = documentRow.Read;
            _lstAcl.Documents[i].ReadRule = documentRow.ReadRule;

            _lstAcl.Documents[i].Create= documentRow.Create;
            _lstAcl.Documents[i].CreateRule = documentRow.CreateRule;

            _lstAcl.Documents[i].Update = documentRow.Update;
            _lstAcl.Documents[i].UpdateRule = documentRow.UpdateRule;

            _lstAcl.Documents[i].Delete = documentRow.Delete;
            _lstAcl.Documents[i].DeleteRule = documentRow.DeleteRule;
        }
    }
}

解決方法は?

この行で例外が発生しているのでしょう。

var documentRow = _dsACL.Documents.First(o => o.ID == id)

First() は、マッチする要素が見つからない場合は例外をスローします。その直後に null をテストしていることからすると、どうやら FirstOrDefault() これは、一致する項目が見つからない場合、要素タイプのデフォルト値 (参照タイプでは null) を返します。

var documentRow = _dsACL.Documents.FirstOrDefault(o => o.ID == id)

その他、状況に応じて考慮すべきオプションは Single() (一致する要素がちょうどひとつだけだと思う場合) と SingleOrDefault() (一致する要素が1つまたは0つだと思うとき)。私が思うに FirstOrDefault このケースでは、他の選択肢も知っておくとよいでしょう。

一方、そもそもここにjoinを入れた方が良いようにも見えます。もし、それが すべて を使用することができます。

var query = from target in _lstAcl.Documents
            join source in _dsAcl.Document
            where source.ID.ToString() equals target.ID
            select new { source, target };
foreach (var pair in query)
{
    target.Read = source.Read;
    target.ReadRule = source.ReadRule;
    // etc
}

もっとシンプルに より効率的だと思います。

たとえ、あなたが する ループを維持することに決めたら、いくつかの提案があります。

  • 外側の if . Count が 0 の場合、for ループのボディは決して実行されないので、これは必要ありません。
  • forループでは排他的上限値を使用する - C#ではより慣用的である。

    for (i = 0; i < _lstAcl.Documents.Count; i++)
    
    
  • 共通する部分式を削除する。

    var target = _lstAcl.Documents[i];
    // Now use target for the rest of the loop body
    
    
  • 可能な場合は foreach の代わりに for を開始します。

    foreach (var target in _lstAcl.Documents)