4

簡単なコードを次に示します。

    static void Main(string[] args)
    {
        var coll = new List<string> {"test", "test2", "test3"};

        var filteredColl = coll.Select(x => x).ToList();

        if (!filteredColl.Any())
        {
            DateTime? date = new DateTime();

            filteredColl = coll.Where(x => date.GetValueOrDefault().Date.ToString(CultureInfo.InvariantCulture) == x).Select(x => x).ToList();
        }
    }

問題は、次の手順で NullReferenceException でクラッシュする理由です

1) if へのブレークポイント

ブレークポイント

2) 次の実行ポイントを設定します。

実行ポイント

3) F10 で続行してみてください:

例外

コードの最後の行をコメントアウトすると、クラッシュしません。

更新: スタック トレースは次のとおりです。

System.NullReferenceException was unhandled   HResult=-2147467261  
Message=Object reference not set to an instance of an object.  
Source=ConsoleApplication28   StackTrace:
       at ConsoleApplication28.Program.Main(String[] args) in Program.cs: line 21
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()   InnerException:
4

2 に答える 2

11

これは、キャプチャされた変数スコープを宣言するコンテキスト内で実行ポイントを移動することの副作用です。これを IDE のバグとして報告するのは合理的ですが、修正するのは簡単ではありません。基本的に、変数dateではありません-ラムダのため、キャプチャコンテキストのフィールドです。コンパイラは基本的に次のことを行います。

if (!filteredColl.Any())
{
    var ctx = new SomeCaptureContext(); // <== invented by the compiler
    ctx.date = new DateTime();

    filteredColl = coll.Where(ctx.SomePredicate).Select(x => x).ToList();
}

どこにSomePredicateある:

class SomeCaptureContext {
    public DateTime? date; // yes, a public field - needs to support 'ref' etc
    public bool SomePredicate(string x) // the actual name is horrible
    {
        return this.date.GetValueOrDefault()
              .Date.ToString(CultureInfo.InvariantCulture) == x;
    }
}

ここでの問題は、実行位置を次の場所にドラッグしたときです。

DateTime? date = new DateTime();

あなたは実際に(IL用語で)それを行にドラッグしています:

ctx.date = new DateTime();

その直前のキャプチャ コンテキスト行、つまり

var ctx = new SomeCaptureContext();

実行されたことがないので、そうctxですnull。したがって、NullReferenceException.

これをバグとして記録するのは合理的ですが、これは微妙なものです。実行コンテキストを常にドラッグしてキャプチャ コンテキストを初期化する必要はありません。「if they are null」である必要があります。

于 2013-09-13T08:31:07.783 に答える
0

うーん...本当に奇妙に見えます。mscorlib は参照にあり、システムは using にありますか? おそらく、DateTime という名前の別のクラスがあり、System.DateTime をオーバーライドします。

于 2013-09-13T08:18:52.490 に答える