返回基础-使用指令的名称空间会影响程序集加载吗?

Jeff Atwood had a great post a while back called "Strong Opinions, Weakly Held." It's good to feel strongly about something, but important to be open to changing your opinion if you're faced with new evidence.

杰夫·阿特伍德(Jeff Atwood)不久前发表了一篇很棒的文章,标题为“强烈的观点,虚弱的举行” 。 对某件事有强烈的感觉是件好事,但如果您面临新的证据,则开放对改变看法的态度很重要。

Last week a reader pointed me to this post at the Microsoft StyleCop blog that shows some interesting examples of using directives outside and inside the namespace declaration.

上周,一位读者向我指出了Microsoft StyleCop博客上的这篇帖子,其中显示了一些在名称空间声明的内部和外部使用指令的有趣示例。

For example, this compiles fine:

例如,这可以正常编译:

using Guid = System.Guid;

namespace Microsoft.Sample
{
public class Guid
{
public Guid(string s){}
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}

}

However this one with the using moved inside the namespace doesn't compile:

但是,这个带有using在名称空间中移动的代码无法编译:

namespace Microsoft.Sample
{
using Guid = System.Guid;

public class Guid
{
public Guid(string s){ }
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}
}

The code fails on the following compiler error, found on the line containing Guid g = new Guid("hello");

代码在包含Guid g = new Guid(“ hello”);的行中发现以下编译器错误时失败。

CS0576: Namespace 'Microsoft.Sample' contains a definition conflicting with alias 'Guid'

CS0576:命名空间“ Microsoft.Sample”包含与别名“ Guid”冲突的定义

In the first example, there's an alias created, but it doesn't matter because the second Guid class is in local scope (there's no scope conflict) and the compiler chooses the inner Guid class.

在第一个示例中,创建了一个别名,但这并不重要,因为第二个Guid类在本地范围内(没有范围冲突),并且编译器选择了内部Guid类。

In the second example, there are two "Guids" declared in the same scope and that's a conflict that the compiler can't resolve automatically. The style rule/argument the post makes is that you will only see these kinds of conflicts if you put your using directives inside your namespaces. To this, I say, "meh." Sure, if it makes you happy and you use lots of namespace aliases, sure, but it's an edge case. I simply prefer to have my namespaces outside.

在第二个示例中,在同一作用域中声明了两个“ Guid”,这是编译器无法自动解决的冲突。 帖子所使用的样式规则/参数是,如果将using指令放在名称空间中,则只会看到这些类型的冲突。 为此,我说“嗯”。 当然,如果它使您满意并且您使用了许多命名空间别名,那么可以肯定,但这是一个极端的情况。 我只是更喜欢将我的名称空间放在外面。

两次阅读,一次测试 (Read Twice, Test Once)

However, the second rule in the post said:

但是,帖子中的第二条规则是:

"However, placing the using statements [Ed. Note: They mean "directives"] within a namespace element allows the framework to lazy load the referenced assemblies at runtime. In some cases, if the referencing code is not actually executed, the framework can avoid having to load one or more of the referenced assemblies completely. This follows general best practice rule about lazy loading for performance."

但是,在名称空间元素中放置using语句[Ed。注意:它们的意思是”指令”]允许框架在运行时延迟加载引用的程序集。在某些情况下,如果未实际执行引用代码,则框架可以避免必须完全加载一个或多个引用的程序集。这遵循有关延迟加载以提高性能的一般最佳实践规则。”

This stopped me in my tracks. This rocks the very bedrock that my knowledge of the CLR stands on. I'm like, NO WAY, and then I oscillated back and forth between denial and acceptance. Then, I settled on denial. I don't buy it. A using directive is for aliasing and is a kind of syntactic sugar. Ultimately the IL is the same. Assembly loading won't be affected as the assembly manifest doesn't change.

这使我停滞不前。 这动摇了我对CLR的了解所依据的基石。 我想,没有办法,然后我在否认和接受之间来回摆动。 然后,我决定拒绝。 我不买using指令用于别名,是一种语法糖。 最终,IL是相同的。 程序集清单不会更改,因此程序集加载不会受到影响。

Here's what my experiment showed. I believe it's true until I find out from someone on the CLR Loader team that it's not true. ;)

这是我的实验显示的内容。 我相信这是真的,直到我从CLR Loader小组的某人那里发现那不是事实。 ;)

第一次测试 (First Test)
using System;
using System.Xml;

namespace Microsoft.Sample
{
public class Program
{
public static void Main(string[] args)
{
Guid g = Guid.NewGuid();
Console.WriteLine("Before XML usage");
Console.ReadLine();
Foo();
Console.WriteLine("After XML usage");
Console.ReadLine();
}

public static void Foo()
{
XmlDocument x = new XmlDocument();
}
}
}

I ran this program outside the debugger but compiled in debug mode. At the point there the first ReadLine() hits, the program pauses and waits for an Enter key. I loaded up Process Explorer and saw:

在调试器之外运行了该程序,但以调试模式进行了编译。 在第一个ReadLine()命中的位置,程序暂停并等待Enter键。 我加载了Process Explorer,然后看到:

image

Then, I hit Enter, executing the Foo() method and new'ing up an XmlDocument. You can see that System.Xml just got loaded (specifically the native image) into the process.

然后,我按下Enter键,执行Foo()方法并新建一个XmlDocument。 您可以看到System.Xml刚被加载到进程中(特别是本机映像)。

image
第二次测试 (Second Test)

If I do the same thing with the usings INSIDE the namespace I get identical results.

如果我对usings INSIDE在名称空间中执行相同的操作,则会得到相同的结果。

namespace Microsoft.Sample
{
using System;
using System.Xml;

public class Program
{
public static void Main(string[] args)
{
Guid g = Guid.NewGuid();
Console.WriteLine("Before XML usage");
Console.ReadLine();
Foo();
Console.WriteLine("After XML usage");
Console.ReadLine();
}

public static void Foo()
{
XmlDocument x = new XmlDocument();
}
}
}

In fact, the only thing that changed the way the assemblies got loaded was switching to release mode. Running the app in release mode had all the assemblies in my trivial app loaded immediately. I thought it was weird for a second, but then realized it had nothing to do with debug vs. release. It was simply that the Foo() method was either inlined or there was a Tail Call Optimization as I explored in this post: Release IS NOT Debug: 64bit Optimizations and C# Method Inlining in Release Build Call Stacks.

实际上,唯一改变组件加载方式的是切换到发布模式。 在发布模式下运行该应用程序会立即加载我琐碎的应用程序中的所有程序集。 我以为这是一秒钟很奇怪,但是后来意识到这与调试与发布无关。 就像我在本文中探讨的那样,很简单地就是内联Foo()方法或进行尾调用优化: Release IS NOT Debug:Release Build Call Stacks中的64位优化和C#方法内联

I'm 99.99% sure at this point that using directives can't change your assembly loading behavior and I think I was right to be suspicious. However, I'm going to ask some people on the Fusion (assembly loader) and C# teams who are smarter than I and I'll update this post as I learn more!

我现在有99.99%的把握使用指令不能改变程序集的加载行为,我认为我是可疑的。 但是,我要问一些融合(程序加载器)和C#团队中比我聪明的人,我将在我了解更多信息的同时更新这篇文章!

However, the Back to Basics Tips here are:

但是,这里的“基本知识”提示是:

  • Don't believe everything you read, even on a Microsoft Blog.

    即使在Microsoft Blog上,也不要相信您阅读的所有内容。
  • Don't believe this blog, either!

    也不要相信该博客!
  • Decide for yourself with experiments if you need a tiebreaker!

    如果您需要决胜局,请自己决定进行实验!

And be ready to be wrong anyway! It only takes one negative experiment to disprove a theory. Of course, the real question is, what does the specification say? 

并准备反正错了! 证明一个理论只需要一个否定的实验。 当然,真正的问题是,规范怎么说?

UPDATE #1: Ian Griffiths had a similar reaction and a similar test!

更新#1:伊恩·格里菲思(Ian Griffiths) 有类似的React和类似的测试

What do you think, Dear Reader?

亲爱的读者,您如何看待?

翻译自: https://www.hanselman.com/blog/back-to-basics-do-namespace-using-directives-affect-assembly-loading

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值