扩展方法性能

时间:2009-06-17 11:52:25

标签: .net-3.5 c#-3.0

            /*I have defined Extension Methods for the TypeX like this*/ 
        public static Int32 GetValueAsInt(this TypeX oValue)
        {
            return Int32.Parse(oValue.ToString());
        }
        public static Boolean GetValueAsBoolean(this TypeX oValue)
        {
            return Boolean.Parse(oValue.ToString());
        }


         TypeX x = new TypeX("1");
         TypeX y = new TypeX("true");


         //Method #1
         Int32 iXValue = x.GetValueAsInt();
         Boolean iYValue = y.GetValueAsBoolean();

         //Method #2
         Int32 iXValueDirect = Int32.Parse(x.ToString());
         Boolean iYValueDirect = Boolean.Parse(y.ToString());

不要被TypeX带走,说我应该在TypeX中定义那些方法而不是Extension。我无法控制它(实际类我定义它在SPListItem上。

我想将TypeX转换为Int或Boolean,这个操作是我在代码中的很多地方做的常见事情。我想知道这会导致性能下降。我试图使用Reflector解释IL代码,但我并不擅长。可能对于上面的例子,不会有任何性能降低。总的来说,我想知道在使用Extension方法时对Regard对Performance的影响。

5 个答案:

答案 0 :(得分:24)

扩展方法只是编译时改变:

x.GetValueAsBoolean()

Extensions.GetValueAsBoolean(x)

这就是所涉及的 - 将看起来像实例方法调用的内容转换为对静态方法的调用。

如果静态方法没有性能问题,那么将其作为扩展方法不会引入任何新问题。

编辑:IL,按照要求......

拿这个样本:

using System;

public static class Extensions
{
    public static void Dump(this string x)
    {
        Console.WriteLine(x);
    }
}

class Test
{
    static void Extension()
    {
        "test".Dump();
    }

    static void Normal()
    {
        Extensions.Dump("test");
    }
}

以下是ExtensionNormal的IL:

.method private hidebysig static void  Extension() cil managed
{
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "test"
  IL_0006:  call       void Extensions::Dump(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Test::Extension

.method private hidebysig static void  Normal() cil managed
{
  // Code size       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "test"
  IL_0006:  call       void Extensions::Dump(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Test::Normal

如您所见,它们完全相同。

答案 1 :(得分:4)

扩展方法只是编译器voodoo,因此它们在运行时具有普通方法的所有性能影响。

答案 2 :(得分:2)

你不会遇到任何性能,因为扩展方法都是在编译时绑定的(你怎么说?)。

答案 3 :(得分:2)

扩展方法可能 很大 会影响编译时间。在我从事的一个大型项目中,只需将扩展方法移至不同的名称空间,我们的编译时间就从15分钟缩短到3分钟。完全相同的代码,只需复制并粘贴到不同的名称空间即可。

如果您考虑将编译时间作为“性能”指标的一部分,那么性能肯定会受到影响。作为开发人员,15分钟的构建时间和3分钟的构建时间很重要。

对我们来说,主要问题是在少数几个命名空间中就有大量扩展方法。每个引用膨胀的名称空间的类或项目(使用using语句)都会导致编译器搜索大量扩展方法。显然,这种搜索不是最佳选择,它会使IDE变慢。 Intellisense的运行速度非常慢,并且反应迟钝。

通过简单地将扩展方法移到单独的,更精细的名称空间中,编译时间就大大减少了。绝对值得考虑。

答案 4 :(得分:1)

在最坏的情况下,你会有一个额外的函数调用。但是,严肃地说,我希望它能够将这些代码内联到尽可能简单并且没有任何明显的效果。