5

我创建了一个单独的程序集来包含常见的扩展方法,扩展方法使用来自System.Web.dll(和其他)的类。

然后,当我创建一个引用包含扩展方法的程序集的新项目(控制台应用程序)时,如果它不使用扩展程序集中任何类Utilities.dll的扩展方法,我不需要添加对新项目的引用(例如)。System.Web.dllSystem.Web.dllSystem.Web.UI.Control

当其中一种扩展方法成为通用方法时,一切都会按预期继续工作。但是,一旦我将约束添加到将其约束到程序集中的类的通用方法中,System.Web.dll编译器就会抱怨我的新项目(控制台应用程序)需要引用,System.Web.dll即使新项目仍然没有使用该程序集中的任何内容.

换句话说,只要我对我的泛型方法没有约束,一切都会编译,但只要我添加约束,编译器就会抱怨。

我的扩展方法 assemble 的一个示例(编译为库Utilities.dll):

public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string value)
    {
        return string.IsNullOrEmpty(value);
    }
}

public static class ControlExtensions
{
    // If I remove the where clause it compiles
    public static T FildChild<T>(this Control parent, string id)
        where T : Control
    {
        throw new NotImplementedException();
    }
}

And here is a new console application that won't compile (unless I also add a reference to System.Web.dll):

    static void Main(string[] args)
    {
        bool isEmpty = "Hello World!".IsNullOrEmpty();

        Console.ReadLine();
    }


Update: As Marc pointed out (below) puting the offending method in a separate namespace fixes the problem.

But the question still remains why is the constraint a problem while the type Control was already used as a parameter to the method. and why is the namespace the solution when I already use the using顶部的指令。

4

2 回答 2

5

嗯,是!为了编译,它需要能够解析公共/受保护 API 中的所有内容。否则它不能强制执行约束。我想它需要识别类型以查看扩展方法是否是方法的候选者。

您可以尝试将扩展方法放在其中包含“Web”的子命名空间中 - 至少它不会溢出到常规代码中。我已经检查过了,这解决了这个问题。分离扩展方法的命名空间以允许调用者控制它们何时应该在范围内是一种很好的做法。

为了执行,它还需要能够解析内部使用但未在 API 中公开的任何内容。这是标准行为。

于 2008-12-18T13:10:48.623 回答
1

@Marc 告诉你原因。我建议作为一种好的做法,您将任何涉及 Web 类的内容分解为另一个程序集,例如 Com.Company.Extensions.Web 和 Com.Company.Extensions。然后,您可以在 Web 项目中包含两者,也可以在其他项目中仅包含非 Web 扩展。

于 2008-12-18T13:17:05.757 回答