2014-12-05 69 views
2

给定一个类和名称空间,定义如下;对未定义名称空间中定义类型的类型推断

namespace Models 
{ 
    public class Foo 
    { 
    } 
} 

而下面......

namespace Factories 
{ 
    using Models; 

    class FooFactory 
    { 
     public Foo GetFoo() 
     { 
      return new Foo(); 
     } 
    } 
} 

最后...

namespace InferenceTest 
{ 
    using Factories; 

    class Program 
    { 
     static void Main() 
     { 
      Foo foo = new FooFactory().GetFoo(); 
     } 
    } 
} 

正如你所期望的,该代码失败,出现错误“的类型或编译名称空间名称'Foo'无法找到(您是否缺少使用指令或程序集引用?)“

但是,如果我行更改为这个...

var foo = new FooFactory().GetFoo(); 

然后编译和运行得很好。

为什么会有这种差异?类型推断是什么使它能够查看尚未导入的名称空间中的类型。命名空间只是语法糖吗?

+0

我不知道这足够好发表权威的答案,但是我会说当你使用'var'你将它留给编译器来确定类型,所以有一个合格的命名空间将是没有帮助的,因为它知道类型是什么。当使用显式类型时,可能指的是具有相同名称(不同名称空间)的不同类型,因此必须明确如何限定类型。 – Lukazoid 2014-12-05 13:43:40

+3

您不必有一个using指令来声明该类型的变量,它只是允许您使用缩短的类型声明。 'Models.Foo foo = new FooFactory()。GetFoo();'会编译得很好。使用var它并不重要什么使用指令,因为你不是说“声明这个特定类型的变量foo”你在说“声明可变foo并从初始化中推断出这个类型”。 – 2014-12-05 13:44:18

+0

噢好吧,所以“var”实际上只是被全限定类型名称替换。“Models.Foo”? – 2014-12-05 13:46:50

回答

2

编译var foo = new FooFactory().GetFoo();的原因很简单。编译器推断foo是Models.Foo类型不仅是Foo。
Models.Foo foo2 = new FooFactory().GetFoo();相似。
请注意,Foo foo2 = new FooFactory().GetFoo();是不同的。

1

namespaces that have not been imported是你无效的原因;你不会导入命名空间,但可以像使用本地一样使用它们。编译过程中唯一导入的是引用程序集,即使它不是真正的导入,只是导入了一些元数据。 (如版本和GUID)

这意味着当您引用程序集(如System.dll)时,可以使用其中的所有类;向您展示它的意义时,我会给你这个反射例如:

internal class Program { 
    private static void Main() { 
     System.Type.GetType("System.Console") 
      .GetMethod("WriteLine",new[] {System.Type.GetType("System.String")}) 
      .Invoke(null,new object[]{"Hello World"}); 
    } 
} 

你没有“进口”的任何命名空间,但仍然使用stringConsoleWriteLine和一些反射功能,而不需要编译器知道它在编译时间,因为您有System.dll引用到您的项目。