2

さて、私の質問のタイトルが複雑すぎることは私には明らかです。できるだけ具体的にしようと思いました。それで、私は問題をよりよく説明しようとします。

問題のコンテキスト

ソリューションに3つの.NETプロジェクトがあると仮定します。メインプロジェクトは、単純なコンソールアプリケーションApplicationAssemblyです。このプロジェクトには、別のマネージアセンブリライブラリDirectlyReferencedLibraryへの参照があります。同時に、DirectlyReferencedLibraryはIndirectlyUsedLibraryを参照します。

したがって、プロジェクトの使用法は次のようになります。ApplicationAssembly- >DirectlyReferencedLibrary->IndirectlyUsedLibrary

ApplicationAssemblyは、IndirectlyUsedLibraryとして宣言されたタイプを直接使用しないことに注意してください。また、これらのアセンブリで宣言されたすべてのタイプが同じ名前空間にあると仮定しましょう。

このソリューションはコンパイルされ、正常に動作します。

奇妙な問題

次の条件を一緒にすると、問題が発生します。

  1. ApplicationAssemblyプロジェクトには、LINQ式の使用法があります。たとえば、列挙可能なタイプのオブジェクトに対してSelect()が呼び出された場合です。
  2. DirectlyReferencedLibraryは、型制限のあるジェネリック拡張メソッドを持つクラスを宣言します。型の制限により、ジェネリック型はIndirectlyUsedLibraryのクラスの子孫である必要があります。

このようなクラスの例を次に示します。

using System;

namespace Test
{
    public static class UnUsedType
    {
        // It's a generic extension method with a type restriction.
        public static void Magic<T>(this T @this)
            // It's a type restriction that uses a type from the IndirectlyUsedLibrary.
            where T : ProblemType
        {
            Console.WriteLine("I do nothing actually.");
        }
    }
}

このプロジェクトをコンパイルしようとすると、次のエラーが発生します。

エラータイプ'Test.ProblemType'は、参照されていないアセンブリで定義されています。アセンブリ'IndirectlyUsedLibrary、Version = 1.0.0.0、Culture = neutral、PublicKeyToken=null'への参照を追加する必要があります。C:\ Projects \ Test \ ApplicationAssembly \ Program.cs 22 13 ApplicationAssembly

質問

なぜそうなのか、誰かが私に理解するのを手伝ってもらえますか?

PS

私は調査のための小さな解決策を作りました。あなたが私を助けてくれてとても親切なら、あなたはここでアーカイブされた解決策を取ることができるでしょう

PPS

英語が下手でごめんなさい。

UPD1

もう1つの奇妙なことは、LINQメソッドの呼び出しが異なると、コンパイル時エラーが発生する場合と発生しない場合があることです。

// Ok. Let's do some work using LINQ we love so much!
var strings = new[] { "aaa", "bbb", "ccc" };
Func<string, object> converter = item => (object) item;

// The following line makes problems.
var asObjects1 = strings.Select(converter);

// Everything is OK if we use the following line:
var asObjects2 = Enumerable.Select(strings, converter);
4

3 に答える 3

14

なぜそうなのかを理解するのを手伝ってくれる人はいますか?

C# コンパイラは、参照されたアセンブリの推移的なクロージャーがコンパイル時に利用可能であるという合理的な期待を持っています。プログラムが投げかけようとしている型解析のすべての問題を解決するために、絶対に必要なもの、必要な可能性があるもの、必要でない可能性があるもの、または絶対に知る必要のないものを推論する高度なロジックはありません。 . アセンブリを直接的または間接的に参照する場合、コンパイラは必要な型情報がそこにあると想定します。

また、コンパイル時に参照アセンブリのセットがない場合、実行時にユーザーがアセンブリを使用することは期待できますか? コンパイル時の環境には、実行時に必要となるアセンブリのセットが少なくとも含まれていると考えるのが妥当と思われます。

やりたくない。

私たちは皆、人生でやりたくないことをしなければなりません。

于 2011-12-21T23:30:03.380 に答える
2

これはご存知だと思いますが、型ProblemTypeは「IndirectlyUsedLibrary」で定義されていますが、拡張メソッドの必須定義であるため、Magicコンパイル時に使用できるように参照する必要があります。

「なぜ」と言うと...そうですね、コンパイラは何をコンパイルしているかの詳細を知る必要がありますね。コンパイラが実行時に必要とするのと同じコンパイル時の参照の最小セットを必要とすることは私には理にかなっています...

于 2011-12-21T23:36:42.277 に答える
1

ライブラリに別の名前空間を使用しても、エラーは発生しません。異なるライブラリ間で同じ名前空間を使用するのは本当に奇妙です。

初めて使用すると、コンパイラが Test 名前空間の拡張機能のスキャンを開始するようです。したがって、参照が必要です。

于 2011-12-21T23:11:59.933 に答える