不包含来自其他构造函数的参数类型时的编译器错误

时间:2014-01-22 16:26:12

标签: c# visual-studio-2012

我在VS2012 v.11.0.61030.00 Update 4下使用C#。我有一个带有两个构造函数的类:一个用于正常使用,另一个为单元测试注入依赖项。

using ServiceLayer;

namespace PresentationLayer
{
    public class Orchestrator
    {
        private NumberService svc;

        public Orchestrator(int i)
        {
            svc = new NumberService(i);
        }

        public Orchestrator(NumberService providedService)
        {
            svc = providedService;
        }

        public int Get()
        {
            return svc.GetInt();
        }
    }
}

“NumberService”是第二个项目:

namespace ServiceLayer
{
    public class NumberService
    {
        private int x;

        public NumberService(int i)
        {
            x = i;
        }

        public int GetInt()
        {
            return x;
        }
    }
}

PresentationLayer项目又由应用程序引用(在本例中为控制台应用程序):

using System;
using PresentationLayer;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Orchestrator o = new Orchestrator(8);
            Console.WriteLine(o.Get());
        }
    }
}

Orchestrator o = new Orchestrator(8);抛出编译器错误,如下所示:

The type 'ServiceLayer.NumberService' is defined in an assembly that is not referenced. You must add a reference to assembly 'ServiceLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

这似乎是因为VS无法在不知道NumberService是什么的情况下区分两个构造函数。但是,如果我改变参数的数量......

public Orchestrator(int i, bool b)
{
    svc = new NumberService(i);
}

static void Main(string[] args)
{
    Orchestrator o = new Orchestrator(8, true);
    Console.WriteLine(o.Get());
}

突然间编译非常乐意。我觉得这两种行为中的一种是错误的:或者不知道给定的类是什么,或者不是。有没有人对此有更好的解释或解决方法?

3 个答案:

答案 0 :(得分:1)

当你知道它的使用是在一个肯定不适合你正在进行的调用的成员中时,不理解某个特定的类是可以的,因为你指定了两个参数,而成员只接受一个参数。

可以不知道调用是否有效,因为您不知道(例如)是否存在从intNumberService的隐式转换。在这种特殊情况下,这不能改变重载分辨率(我认为 ...)但在其他情况下可能会改变。想象一下,如果您的int参数实际上是object,例如......

就个人而言,我会非常谨慎地使用一个类,其中某些公共API依赖于您没有引用的程序集中的类型。你在黑暗中有点操作。我建议你只需添加一个合适的引用,或者使构造函数内部从公共API中删除它。拥有一个你不实际希望其他代码能够理解的公共API是没有意义的。如果这只是为了单元测试,那么使构造函数internal并使用InternalsVisibleTo将它(以及其他内部成员)暴露给您的单元测试程序集。

答案 1 :(得分:0)

这是一个有根据的猜测 - 我没有检查语言规范来证实这一点 - 但我想象编译器会根据许多标准选择重载。如果给定方法有20个重载,则忽略具有与您正在进行的调用的参数数量不同的重载的效率要高得多,因为这些显然是而不是被调用的那个。 / p>

但是,一旦你缩小到与传递的参数数量相同的重载列表,它就会更复杂:可能存在从传递给其中一个重载类型的隐式转换,例如,这使分辨率不清楚。如果编译器不知道所有可用参数的类型,它就无法可靠地做出决定而失败。

添加额外参数意味着它永远不需要使用NumberService来查看重载,因此编译器不需要汇编引用来解决重载。

答案 2 :(得分:0)

您可以通过启用依赖注入的构造函数重载internal来消除错误,从而使编译器无需知道int是否可以转换为numberService