Es passiert mir nur mit einer Frage zum Code-Design. Sagen wir, ich habe eine "Template" -Methode, die einige Funktionen aufruft, die sich "ändern" können. Ein intuitives Design folgt "Template Design Pattern". Definieren Sie die Änderungsfunktionen als "virtuelle" Funktionen, die in Unterklassen überschrieben werden sollen. Oder ich kann Delegiertenfunktionen einfach ohne "virtuell" verwenden. Die Delegate-Funktionen sind injiziert, so dass sie auch angepasst werden können.C#: Virtual Function-Aufruf ist sogar schneller als ein Delegat-Aufruf?
Ursprünglich dachte ich, der zweite "Delegierten" Weg wäre schneller als "virtueller" Weg, aber einige Codeschnipsel beweist, dass es nicht korrekt ist.
Im folgenden Code folgt die erste DoSomething-Methode "Vorlagenmuster". Es ruft die virtuelle Methode IsTokenChar auf. Die zweite DoSomthing-Methode hängt nicht von der virtuellen Funktion ab. Stattdessen hat es einen Pass-In-Delegaten. In meinem Computer ist das erste DoSomthing immer schneller als das zweite. Das Ergebnis ist wie 1645: 1780.
"Virtueller Aufruf" ist dynamische Bindung und sollte mehr Zeit kosten als direkter Aufruf der Delegation, nicht wahr? aber das Ergebnis zeigt, dass es nicht ist.
Jeder kann das erklären?
using System;
using System.Diagnostics;
class Foo
{
public virtual bool IsTokenChar(string word)
{
return String.IsNullOrEmpty(word);
}
// this is a template method
public int DoSomething(string word)
{
int trueCount = 0;
for (int i = 0; i < repeat; ++i)
{
if (IsTokenChar(word))
{
++trueCount;
}
}
return trueCount;
}
public int DoSomething(Predicate<string> predicator, string word)
{
int trueCount = 0;
for (int i = 0; i < repeat; ++i)
{
if (predicator(word))
{
++trueCount;
}
}
return trueCount;
}
private int repeat = 200000000;
}
class Program
{
static void Main(string[] args)
{
Foo f = new Foo();
{
Stopwatch sw = Stopwatch.StartNew();
f.DoSomething(null);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
{
Stopwatch sw = Stopwatch.StartNew();
f.DoSomething(str => String.IsNullOrEmpty(str), null);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
}
One für Jon Skeet, fühle ich mich! ;) –
@Mitch: Ich hatte deinen Kommentar vor der Beantwortung noch nicht gesehen, aber ich fühle mich geschmeichelt :) –
Btw, ich finde den Unterschied besser mit einem optimierten Build markiert zu sein –