在C#中为什么这样访问嵌套命名空间的类不对?【解决】
作者:admin 时间:2023-4-27 19:54:13 浏览:在C#中,访问嵌套命名空间的类的时候,你如果是一个新手,或者对C#嵌套命名空间的了解还不够透彻,那么就有可能出现如本文中的错误。
问题
有如下嵌套命名空间代码:
namespace n1
{
namespace n2
{
class foo{}
}
}
我用如下写法调用类foo:
using n1;
n2.foo something;
但是这样写不对!
那么该如何写才对呢?
解答一
这是 C# 的规则,如果你这样做:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
class Foo
{
Magic.Lamp myLamp; // 合规;
}
}
那是合规的,当Magic在Frobozz里时,Magic的意思是Frobozz.Magic。但下面代码不是:
namespace Frobozz
{
namespace Magic
{
class Lamp {}
}
}
namespace Flathead
{
using Frobozz;
class Bar
{
Magic.Lamp myLamp; // 不合规
}
}
这是不合规的,仅仅使用Frobozz并不能将Magic带入范围。
描述这一点的 C# 规则在 C# 4 规范的第 7.6.2 节中。这是一个非常混乱的部分;你想要的是靠近末尾的段落:
否则,如果命名空间声明的 using-namespace-directives 导入的命名空间恰好包含一个名称为 ... 的类型......
关键是它说的是“恰好是一种类型”,而不是“恰好是一种类型或命名空间”。当你在该名称空间之外时,我们不允许你像这样“切片”命名空间名称,因为它可能会造成混淆。正如其他人所说,如果你想做那种事情,请在使用别名(using-alias)指令中完全限定一次,然后使用别名。
使用命名空间别名:
using n2 = n1.n2;
...
n2.foo something;
类名之前应该是一个完整的命名空间(带有/或嵌套类型的其他类名),截断的命名空间将不起作用。
解答二
通过设计,命名空间可以帮助你定义范围。
除非你完全限定它,否则你会得到你所看到的错误。
假设你有这样的代码:
namespace n1
{
namespace n2
{
class Foo { }
}
}
你可以通过两种方式执行此操作。
1、使用完全限定名称
代码:
namespace n3
{
using n1.n2;
class TestClass
{
private Foo something;
}
}
2、用一个别名
代码:
namespace n3
{
using n2 = n1.n2;
class TestClass
{
private n2.Foo something;
}
}
解答三
C# 语言规范中的第 9.4.2 节第 4 段明确解释了此行为:
using-namespace-directive导入给定命名空间中包含的类型,但特别是不导入嵌套的命名空间。
它甚至继续举了一个与你自己的非常相似的例子。
namespace N1.N2
{
class A {}
}
namespace N3
{
using N1;
class B: N2.A {} // 错误, N2未知
}
然而,如果你把代码改为这样:
namespace n1
{
public class Example
{
public static void Main()
{
n2.Foo a; // 这是合规的
}
}
}
这将编译,因为n2是可访问的,它是从原型命名空间块中引用的。
解答四
一种方法是将嵌套的命名空间声明为类。
比如你有如下代码:
namespace NS1
{
public class NNS1
{
public class C { }
}
}
namespace NS2
{
public class NNS2
{
public class C { }
}
}
然后通过以下方式使用你的命名空间:
using NS1;
using NS2;
class C
{
public C()
{
var c1 = new NNS1.C();
var c2 = new NNS2.C();
}
}
但是,这不能创建命名空间的联合,如果你有:
namespace NS1
{
public class NNS
{
public class C1 { }
}
}
namespace NS2
{
public class NNS
{
public class C2 { }
}
}
和
using NS1;
using NS2;
class C
{
public C()
{
var c1 = new NNS.C1();
var c2 = new NNS.C2();
}
}
编译器会认为NNS有歧义义,因为它可以在这个上下文中引用两个类符号。我试图将命名空间声明为接口,并使用一个类来实现它们以创建命名空间的联合,但是,实现接口不会自动在其中导入嵌套类符号。
相关文章
- 站长推荐