10

エラーの原因となる部分だけが正確にはわからないため、ラベルを付ける方法が完全にはわかりません。

この質問は、SO質問の副産物です。c#コードは、オブジェクト値がnullになるように無効な方法で最適化されているようです。これは、昨日の夕方にGaryを支援しようとしました。彼は問題があることを知った人でした。私は問題をより単純なプロジェクトに減らしたところです。さらに先に進む前に検証が必要なので、ここでこの質問をします。

他の人もこの問題を抱えていることを確認できる場合は、Microsoft Connectにメモを投稿します。もちろん、Jon、Mads、Ericのいずれかが問題を確認してくれることを願っています:)

これには以下が含まれます。

  • 3つのプロジェクト。そのうちの2つはクラスライブラリで、そのうちの1つはコンソールプログラムです(この最後のプロジェクトは問題を再現するために必要ではありませんが、これを実行するだけで問題が表示されますが、リフレクターを使用してコンパイルされたコードを確認する必要があります追加しない場合)
  • 不完全な参照と型推論
  • ジェネリック

コードはここから入手できます:コードリポジトリ

手を汚したい場合は、プロジェクトの作り方を以下に説明します。

この問題は、単純な汎用リストを返す前に、メソッド呼び出しで無効なキャストを生成し、それを返す前に奇妙なものにキャストすることによって現れます。元のコードは、ブール値へのキャストで終了しました。はい、ブール値です。コンパイラーはList<SomeEntityObject>、結果を返す前に、からブール値へのキャストを追加し、メソッドのシグニチャーは、を返すと述べましたList<SomeEntityObject>。これにより、実行時に奇妙な問題が発生し、メソッド呼び出しの結果が「最適化された」(元の質問)と見なされたり、同様の例外のいずれBadImageFormatExceptionかまたは1つでクラッシュしたりします。InvalidProgramException

これを再現する作業中に、へのキャストを確認しました。void[]現在のバージョンのコードはにキャストされていTypedReferenceます。あるケースでは、Reflectorがクラッシュするため、その場合、コードが期待を超えていた可能性があります。マイレージは異なる場合があります。

これを再現するために行うことは次のとおりです。

注:問題を再現する最小限のフォームがもっとある可能性がありますが、すべてのコードを1つのプロジェクトに移動するだけで問題は解決しました。クラスからジェネリックを削除すると、問題も解消されます。以下のコードは毎回問題を再現しているので、そのままにしておきます。

以下のコードでエスケープされたhtml文字をお詫びします。これはMarkdownが私をだましていることです。誰かが私がそれを修正する方法を知っている場合は、私に知らせてください。または質問を編集してください。

  1. .NET4.0用のコンソールアプリケーションを含む新しいVisualStudio2010ソリューションを作成します
  2. 2つの新しいプロジェクトを追加します。どちらもクラスライブラリであり、.NET 4.0でもあります(ClassLibrary1とClassLibrary2という名前であると想定します)
  3. クライアントプロファイルだけでなく、完全な.NET4.0ランタイムを使用するようにすべてのプロジェクトを調整します
  4. コンソールプロジェクトの参照をClassLibrary2に追加します
  5. ClassLibrary2の参照をClassLibrary1に追加します
  6. デフォルトでクラスライブラリに追加された2つのClass1.csファイルを削除します
  7. ClassLibrary1で、System.Runtime.Cachingへの参照を追加します
  8. ClassLibrary1に新しいファイルを追加し、それをDummyCache.csと呼び、次のコードを貼り付けます。

    using System;
    using System.Collections.Generic;
    using System.Runtime.Caching;
    
    namespace ClassLibrary1
    {
        public class DummyCache<TModel> where TModel : new()
        {
            public void TriggerMethod<T>()
            {
            }
            // Try commenting this out, note that it is never called!
            public void TriggerMethod<T>(T value, CacheItemPolicy policy)
            {
            }
            public CacheItemPolicy GetDefaultCacheItemPolicy()
            {
                return null;
            }
            public CacheItemPolicy GetDefaultCacheItemPolicy(IEnumerable<string> dependentKeys, bool createInsertDependency = false)
            {
                return null;
            }
        }
    }
    
  9. ClassLibrary2に新しいファイルを追加し、それをDummy.csと呼び、次のコードを貼り付けます。

    using System;
    using System.Collections.Generic;
    using ClassLibrary1;
    
    namespace ClassLibrary2
    {
        public class Dummy
        {
            private DummyCache<Dummy> Cache { get; set; }
            public void TryCommentingMeOut()
            {
                Cache.TriggerMethod<Dummy>();
            }
            public List<Dummy> GetDummies()
            {
                var policy = Cache.GetDefaultCacheItemPolicy();
                return new List<Dummy>();
            }
        }
    }
    
  10. コンソールプロジェクトのProgram.csに次のコードを貼り付けます。

    using System;
    using System.Collections.Generic;
    using ClassLibrary2;
    
    namespace ConsoleApplication23
    {
        class Program
        {
            static void Main(string[] args)
            {
                Dummy dummy = new Dummy();
                // This will crash with InvalidProgramException
                // or BadImageFormatException, or a similar exception
                List<Dummy> dummies = dummy.GetDummies();
            }
        }
    }
    
  11. ビルドし、コンパイラエラーがないことを確認します

  12. プログラムを実行してみてください。これは、より恐ろしい例外の1つでクラッシュするはずです。キャストの結果に応じて、InvalidProgramExceptionとBadImageFormatExceptionの両方を見てきました
  13. Reflectorで生成されたDummy.GetDummiesのコードを見てください。ソースコードは次のようになります。

    public List<Dummy> GetDummies()
    {
        var policy = Cache.GetDefaultCacheItemPolicy();
        return new List<Dummy>();
    }
    

    ただし、リフレクターは次のように述べています(私にとっては、選択したキャストが異なる場合があり、場合によってはリフレクターがクラッシュすることもあります)。

    public List<Dummy> GetDummies()
    {
        List<Dummy> policy = (List<Dummy>)this.Cache.GetDefaultCacheItemPolicy();
        TypedReference CS$1$0000 = (TypedReference) new List<Dummy>();
        return (List<Dummy>) CS$1$0000;
    }
    

さて、ここにいくつかの奇妙なことがあります、上記のクラッシュ/無効なコードは別として:

  • を持つLibrary2は、Dummy.GetDummiesLibrary1からクラスのデフォルトのキャッシュポリシーを取得するための呼び出しを実行します。型推論を使用var policy = ...し、結果はCacheItemPolicyオブジェクトになります(コードではnullですが、型は重要です)。

    ただし、ClassLibrary2にはSystem.Runtime.Cachingへの参照がないため、コンパイルしないでください。

    実際、Dummyで名前が付けられたメソッドをコメントアウトするとTryCommentingMeOut、次のようになります。

    タイプ'System.Runtime.Caching.CacheItemPolicy'は、参照されていないアセンブリで定義されています。アセンブリ'System.Runtime.Caching、Version = 4.0.0.0、Culture = neutral、PublicKeyToken=b03f5f7f11d50a3a'への参照を追加する必要があります。

    なぜこのメソッドが存在するのか、コンパイラーが幸せになるのか、私にはわかりません。また、これが現在の問題に関連しているかどうかさえわかりません。おそらくそれは2番目のバグです。

  • に同様のメソッドがありDummyCacheます。でメソッドを復元しDummyて、コードを再度コンパイルし、DummyCacheその上に「これをコメントアウトしてみてください」というコメントが付いているメソッドをコメントアウトすると、同じコンパイラエラーが発生します。

4

1 に答える 1

2

OK、コードをダウンロードしました。説明どおりに問題を確認できます。

私はこれで大規模ないじくり回しをしていませんが、リリースビルドを実行してリフレクターすると、すべて問題ないようです(= null ref例外とクリーンな分解)。
リフレクター(6.10.11)がデバッグビルドでクラッシュしました。

もう1つの実験:CacheItemPoliciesの使用について疑問に思ったので、それを自分のMyCacheItemPolicy(3番目のclasslib内)に置き換えたところ、同じBadImageFormat例外がポップアップしました。

例外は次のように述べています:{"不正なバイナリ署名。(HRESULTからの例外:0x80131192)"}

于 2010-08-01T18:27:51.093 に答える