我刚刚修改了深度C#的第4章,它处理了可空类型,我正在添加一个关于使用"as"运算符的部分,它允许你编写:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
Run Code Online (Sandbox Code Playgroud)
我认为这非常简洁,它可以提高性能而不是C#1等效,使用"is"后跟一个演员 - 毕竟,这样我们只需要请求动态类型检查一次,然后进行简单的值检查.
然而,情况似乎并非如此.我在下面包含了一个示例测试应用程序,它基本上对对象数组中的所有整数求和 - 但该数组包含许多空引用和字符串引用以及盒装整数.该基准测试您必须在C#1中使用的代码,使用"as"运算符的代码,以及用于踢LINQ解决方案的代码.令我惊讶的是,在这种情况下,C#1代码的速度提高了20倍 - 即使是LINQ代码(考虑到所涉及的迭代器,我预计它会更慢)也胜过"as"代码.
可以isinst为空的类型的.NET实现真的很慢吗?是unbox.any导致问题的附加因素吗?还有另一种解释吗?目前,我觉得我必须在性能敏感的情况下包含警告,禁止使用它...
结果:
演员:10000000:121
As:10000000:2211
LINQ:10000000:2143
码:
using System;
using System.Diagnostics;
using System.Linq;
class Test
{
const int Size = 30000000;
static void Main()
{
object[] values = new object[Size];
for (int i = 0; i < Size - 2; i += 3)
{
values[i] = null;
values[i+1] …Run Code Online (Sandbox Code Playgroud) 我非常怀疑C#或.NET JIT编译器是否执行任何有用的优化,更不用说如果它们实际上与C++编译器中最基本的编译器竞争.
考虑这个非常简单的程序,我方便地在C++和C#中都有效:
#if __cplusplus
#else
static class Program
{
#endif
static void Rem()
{
for (int i = 0; i < 1 << 30; i++) ;
}
#if __cplusplus
int main()
#else
static void Main()
#endif
{
for (int i = 0; i < 1 << 30; i++)
Rem();
}
#if __cplusplus
#else
}
#endif
Run Code Online (Sandbox Code Playgroud)
当我在发布模式下在最新版本的C#(VS 2013)中编译并运行它时,它不会在任何合理的时间内终止.
编辑:这是另一个例子:
static class Program
{
private static void Test2() { }
private static void Test1()
{
#if TEST
Test2(); …Run Code Online (Sandbox Code Playgroud) 我知道这个关键字的功能,但我想知道它是如何在较低级别上工作的.
哪一个更快?他们总能产生相同的结果吗?如果他们这样做,为什么有两种不同的方式?
// Is there an overhead? An internal try catch?
Class123 obj = someobject as Class123;
if (Class123 != null)
{
//OK
}
Run Code Online (Sandbox Code Playgroud)
要么
Class123 obj = null;
if (someobject is Class123)
{
obj = (Class123)someobject;
}
Run Code Online (Sandbox Code Playgroud)