gpt4 book ai didi

c# - "using static"杀死 AsParallel

转载 作者:行者123 更新时间:2023-12-03 15:01:18 26 4
gpt4 key购买 nike

在以下代码中,如果取消注释“using static”行,查询将不会并行运行。为什么?
(Visual Studio 社区 2019,.Net Core 3.1/.Net 4.8)

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;

namespace UsingStatic_Mystery
{
//using static Enumerable;
class Program
{
static void Main(string[] args)
{
var w = new Stopwatch();
iter:
w.Start();
var xx = Enumerable.Range(0, 10)
.AsParallel()
.OrderByDescending(x => {
Thread.Sleep(new Random().Next(100));
Console.WriteLine(x);
return x;
}).ToArray();
w.Stop();
Console.WriteLine();
foreach (var x in xx) Console.WriteLine(x);
Console.WriteLine(w.ElapsedMilliseconds);
Console.ReadLine();
w.Reset();
goto iter;
}
}
}
输出,未注释/注释:
"using static" uncommented
"using static" commented

最佳答案

成立:
这是IL code generatedusing static评论(所以 没有 using static ):

IL_0038: call class [System.Linq.Parallel]System.Linq.OrderedParallelQuery`1<!!0> [System.Linq.Parallel]System.Linq.ParallelEnumerable::OrderByDescending<int32, int32>(class [System.Linq.Parallel]System.Linq.ParallelQuery`1<!!0>, class [System.Private.CoreLib]System.Func`2<!!0, !!1>)
IL_003d: call !!0[] [System.Linq.Parallel]System.Linq.ParallelEnumerable::ToArray<int32>(class [System.Linq.Parallel]System.Linq.ParallelQuery`1<!!0>)
这是 IL code generatedusing static未注释(所以 using static ):
IL_0038: call class [System.Linq]System.Linq.IOrderedEnumerable`1<!!0> [System.Linq]System.Linq.Enumerable::OrderByDescending<int32, int32>(class [System.Private.CoreLib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Private.CoreLib]System.Func`2<!!0, !!1>)
IL_003d: call !!0[] [System.Linq]System.Linq.Enumerable::ToArray<int32>(class [System.Private.CoreLib]System.Collections.Generic.IEnumerable`1<!!0>)
“正确”的一面是使用 Parallel.OrderBy ,“错误”的一方正在使用 Enumerable.OrderBy .由于这个原因,您看到的结果非常清楚。以及为什么一个或另一个的原因 OrderBy被选中是因为与 using static Enumerable您声明 C# 应该更喜欢 Enumerable 中的方法类(class)。
更有趣的是,你有没有像这样编写 using 块:
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;

using static System.Linq.Enumerable;

namespace ConsoleApp1
{
所以在命名空间之外,一切都会“正确”地工作( IL code generated )。
I'll say that namespace resolution works by level...首先 C# 尝试所有 using定义在 namespace 的最内层,如果没有足够好的人,那么它会上升 namespace 的水平。 .如果有多个候选人 同级它需要最好的匹配。在没有 using static 的示例中以及我给出的示例 using + using static都是顶级的,只有一个级别,所以 C# 是最好的候选人。在两级 using检查最里面的一个,然后 using static Enumerable足以解决 OrderBy方法,所以没有做额外的检查。
这次我再说一遍, SharpLab是这个回应的MVP。如果您对 C# 编译器在幕后做了什么有疑问,SharpLab 可以给您答复(从技术上讲,您可以使用 ildasm.exeILSpy ,但 SharpLab 非常直接,因为它是一个网站,您可以交互式地更改源代码)。 SVP(第二个有值(value)的球员)(对我来说)是 WinMerge,我用来比较 IL 程序集😀
回复评论
C# 6.0 draft reference页面说

The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.


进而

Ambiguities between multiple using_namespace_directives and using_static_directives are discussed in Using namespace directives.


所以第一条规则甚至适用于 using static .这解释了为什么第三个例子(我的)等价于 no- using static .
关于为什么 ParallelEnumerable.OrderedBy()优于 Enumerable.OrderBy()当它们都被 C# 编译器检查时,很简单: AsParallel()返回 ParallelQuery<TSource> (实现 IEnumerable<TSource> ) ParallelEnumerable.OrderedBy()签名:
public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
Enumerable.OrderedBy()签名:
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
第一个接受 ParallelQuery<TSource> ,这与 AsParallel() 返回的类型完全相同,不需要“沮丧”。

关于c# - "using static"杀死 AsParallel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65972505/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com