间接引用声明具有类型限制的泛型扩展方法的程序集时出现奇怪的编译错误

时间:2011-12-21 22:55:25

标签: c# .net generics extension-methods generic-method

嗯,我很清楚我的问题标题太复杂了。我只是想尽可能具体。所以,我会尝试更好地解释这个问题。

问题背景

假设我们在解决方案中有三个.NET项目。主项目是一个简单的控制台应用程序 ApplicationAssembly 。此项目引用了另一个托管程序集库 DirectlyReferencedLibrary 。同时DirectlyReferencedLibrary引用 IndirectlyUsedLibrary

所以,项目用法看起来像这样: ApplicationAssembly - > DirectlyReferencedLibrary - > IndirectlyUsedLibrary

请注意,ApplicationAssembly并不直接使用任何声明为IndirectlyUsedLibrary的类型。我们还假设这些程序集中声明的所有类型都位于同一名称空间中。

此解决方案可编译并正常运行。

奇怪的问题

当我在一起时遇到以下情况时会出现问题:

  1. ApplicationAssembly 项目具有LINQ表达式的用法。例如,如果在可枚举类型的任何对象上调用Select()。
  2. DirectlyReferencedLibrary 声明一个具有类型限制的通用扩展方法的类。类型限制表示泛型类型必须是 IndirectlyUsedLibrary 中类的后代。
  3. 以下是此类的示例。

    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.");
            }
        }
    }
    

    当我尝试编译这个项目时,我收到以下错误:

      

    错误类型&#39; Test.ProblemType&#39;在未引用的程序集中定义。你必须添加一个对assembly&#39; IndirectlyUsedLibrary,Version = 1.0.0.0,Culture = neutral,   公钥=空&#39 ;. C:\ Projects \ Test \ ApplicationAssembly \ Program.cs 22 13 ApplicationAssembly

    问题

    任何人都可以帮我理解为什么会这样吗?

    P.S。

    我做了一个很小的调查解决方案。 如果您非常友好地帮助我,您将可以 an archived solution here

    P.P.S。

    抱歉我的英语不好。

    UPD1

    另一个奇怪的事情是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);
    

3 个答案:

答案 0 :(得分:14)

  

任何人都可以帮我理解为什么会这样吗?

C#编译器合理地期望在引用时可以使用引用程序集的传递闭包。它没有任何类型的高级逻辑可以解释它确实需要的,可能需要的,可能不需要的,或者肯定不需要知道为了解决类型分析中的所有问题,你的程序将抛出它。如果直接或间接引用程序集,则编译器会假定其中可能存在所需的类型信息。

另外,如果在编译时没有引用程序集的集合,那么用户在运行时会有什么期望呢?期望编译时环境至少具有在运行时需要的一组程序集似乎是合理的。

  

我不想这样做。

我们都必须做我们生活中不想做的事情。

答案 1 :(得分:2)

我认为您知道这一点,但因为类型ProblemType在“IndirectlyUsedLibrary”中定义,但是Magic扩展方法的必需定义,必须引用它才能在编译时可用。

关于“为什么”......好吧,编译器需要知道它编译的细节不是吗?对我来说,编译器需要在运行时需要的最小编译时引用集合才有意义......

答案 2 :(得分:1)

如果对库使用不同的命名空间,则不会出现错误。在不同的库中使用相同的命名空间真的很奇怪。

看起来编译器在您第一次使用any时会开始扫描您的Test命名空间中的扩展名。因此需要参考。