当前位置:  开发笔记 > 编程语言 > 正文

TypeCasting的表现

如何解决《TypeCasting的表现》经验,为你挑选了2个好方法。

两者之间是否有任何可测量的性能差异

((TypeA) obj).method1();
((TypeA) obj).method2();
((TypeA) obj).method3();

var A = (TypeA) obj;
A.method1();
A.method2();
A.method3();

什么时候使用?

我经常看到类似的东西

if (((TextBox)sender).Text.Contains('.') || ((TextBox)sender).Text.Contains(','))

并想知道这是否是对性能的浪费.



1> Jon Skeet..:

如果用很少的其他工作完成数十亿次,这可能是可测量的.我不知道CLR是否会有效地缓存转换工作的事实,因此它不需要再次执行 - 如果它现在不这样做,它可能会在以后的版本中这样做.它可能在64位JIT但不是32位版本中这样做,反之亦然 - 你明白了.我怀疑它会在普通代码中产生重大影响.

我个人更喜欢第二种形式的可读性,而且到目前为止更为重要.


同意,虽然我经常看到"as"在使用演员*时被使用.通常"错误的类型"=="bug",在这种情况下,简单的演员是正确的方法.
+1我还认为应该使用"as"运算符完成类型转换,并在以后检查为null,除非你*要*抛出异常.
(当然,如果强制转换失败,则isinst的速度会大大提高*,但是我们所谈论的是一种非常不同的情况,两者之间的* result *根本不同。当强制转换成功时,以及当强制转换成功时直接转换而不是用户转换,效果应该大致相同。)

2> Robert Venab..:

@dkson:我测试了两种方法.这是我在计算机上找到的内容:

他们对相同的性能.事实上,我发现第二种方法稍慢.原因(我相信)是额外变量和初始演员的成本.当然,如果你使用足够的演员阵容,你可能会获得性能成本.只有在节省了20-30次演员之后,你才能在表演方面实现收支平衡.

以下是最近两次测试运行的结果:

TestMuliCast\_3x:      00:00:00.5970000   
TestSingleCast\_3x:    00:00:00.6020000   
TestMuliCast\_30x:     00:00:06.0930000   
TestSingleCast\_30x:   00:00:06.0480000   

TestMuliCast\_3x:      00:00:00.6120000   
TestSingleCast\_3x:    00:00:00.6250000   
TestMuliCast\_30x:     00:00:06.5490000   
TestSingleCast\_30x:   00:00:06.4440000   

我也测试了castclass和之间的区别isinst.根据我读过的内容:

http://m3mia.blogspot.com/2007/11/comparing-isinst-to-castclass.html
http://www.codeproject.com/KB/cs/csharpcasts.aspx
http://discuss.joelonsoftware.com/ Default.asp的?dotnet.12.635066.13

我认为即使没有例外,isinst也会比castclass快.但是,在创建自己的基准测试后,我发现isinst 比castclass 略.很有意思.这是我的结果:

TestEmptyLoop:        00:00:00.0870000   
TestDCast\_castclass:  00:00:00.2640000   
TestDCast\_isinst:     00:00:00.3780000   

TestEmptyLoop:        00:00:00.0870000   
TestDCast\_castclass:  00:00:00.2600000   
TestDCast\_isinst:     00:00:00.3750000   

所以,斯基特先生,我的立场得到了纠正.

环境:

Windows Vista
最高核心速度3.2Ghz
.NET Framework v2.0.50727

以下是我创建和运行的基准测试的完整来源:(使用此处提供的Jon Skeets Microbenchmarking框架)

using System;   
using System.Collections;

public class CastingBenchmark   
{
    static Int64 Iterations=100000000;
    static Int64 TestWork = 0;

    public static void Init(string[] args)
    {
        if (args.Length>0)
            Iterations = Int64.Parse(args[0]);
    }

    public static void Reset()
    {
        TestWork = 0;
    }

    internal class BaseType { public void TestBaseMethod() { TestWork++; } }

    internal class DerivedType : BaseType { 
        public void TestDerivedMethod() { TestWork++; }
        public void TestDerivedMethod2() { TestWork++; }
        public void TestDerivedMethod3() { TestWork++; } 
}

[Benchmark]
public static void TestMuliCast_3x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        ((DerivedType)TestBaseType).TestDerivedMethod();
        ((DerivedType)TestBaseType).TestDerivedMethod2();
        ((DerivedType)TestBaseType).TestDerivedMethod3();
    }
}

[Benchmark]
public static void TestSingleCast_3x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        DerivedType TestDerivedType = (DerivedType)TestBaseType;
        TestDerivedType.TestDerivedMethod();
        TestDerivedType.TestDerivedMethod2();
        TestDerivedType.TestDerivedMethod3();
    }
}

[Benchmark]
public static void TestMuliCast_30x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        //Simulate 3 x 10 method calls while casting
        for (int y = 0; y < 10; y++) {

            ((DerivedType)TestBaseType).TestDerivedMethod();
            ((DerivedType)TestBaseType).TestDerivedMethod2();
            ((DerivedType)TestBaseType).TestDerivedMethod3();
        }
    }
}

[Benchmark]
public static void TestSingleCast_30x()
{
    BaseType TestBaseType = new DerivedType();

    for (int x = 0; x < Iterations; x++)
    {
        DerivedType TestDerivedType = (DerivedType)TestBaseType;

        //Simulate 3 x 10 method calls on already-cast object
        for (int y = 0; y < 10; y++)
        {
            TestDerivedType.TestDerivedMethod();
            TestDerivedType.TestDerivedMethod2();
            TestDerivedType.TestDerivedMethod3();
        }
    }
}

    [Benchmark]
    public static void TestEmptyLoop()
    {
        for (int x = 0; x < Iterations; x++)
        {
        }
    }

    [Benchmark]
    public static void TestDCast_castclass()
    {
        BaseType TestDerivedType = new DerivedType();

        for (int x = 0; x < Iterations; x++)
        {
            ((DerivedType)TestDerivedType).TestDerivedMethod();
        }    
    }

    [Benchmark]
    public static void TestDCast_isinst()
    {
        BaseType TestDerivedType = new DerivedType();

        for (int x = 0; x < Iterations; x++)
        {
            (TestDerivedType as DerivedType).TestDerivedMethod();
        }
    }
}

由此产生的IL isinstcastclass方法:

method public hidebysig static void TestDCast_isinst() cil managed
{
    .custom instance void BenchmarkAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] class CastingBenchmark/BaseType TestDerivedType,
        [1] int32 x)
    L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
    L_0005: stloc.0 
    L_0006: ldc.i4.0 
    L_0007: stloc.1 
    L_0008: br.s L_0019
    L_000a: ldloc.0 
    L_000b: isinst CastingBenchmark/DerivedType
    L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
    L_0015: ldloc.1 
    L_0016: ldc.i4.1 
    L_0017: add 
    L_0018: stloc.1 
    L_0019: ldloc.1 
    L_001a: conv.i8 
    L_001b: ldsfld int64 CastingBenchmark::Iterations
    L_0020: blt.s L_000a
    L_0022: ret 
}

.method public hidebysig static void TestDCast_castclass() cil managed
{
    .custom instance void BenchmarkAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] class CastingBenchmark/BaseType TestDerivedType,
        [1] int32 x)
    L_0000: newobj instance void CastingBenchmark/DerivedType::.ctor()
    L_0005: stloc.0 
    L_0006: ldc.i4.0 
    L_0007: stloc.1 
    L_0008: br.s L_0019
    L_000a: ldloc.0 
    L_000b: castclass CastingBenchmark/DerivedType
    L_0010: callvirt instance void CastingBenchmark/DerivedType::TestDerivedMethod()
    L_0015: ldloc.1 
    L_0016: ldc.i4.1 
    L_0017: add 
    L_0018: stloc.1 
    L_0019: ldloc.1 
    L_001a: conv.i8 
    L_001b: ldsfld int64 CastingBenchmark::Iterations
    L_0020: blt.s L_000a
    L_0022: ret 
}

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有