You are calling a method that takes very little time. Which makes the overhead in calling the method a major contributing factor in the speed of the code. Both the dynamic invoke and inability to inline the method are the time killers. You can see the difference by moving the inner loop inside the Calculate method. For example:
sb.Append("public double Calculate(double x, double y){\n");
sb.Append("double sum = 0; for (; y <= 500; y += 0.1) {\n");
sb.Append("sum += " + sCSCode + ";\n");
sb.Append("} return sum;\n");
and
long t2 = DateTime.Now.Ticks;
for (double x = 0; x <= 500; x += 0.1) {
sum += f2(x, 0);
}
t2 = DateTime.Now.Ticks - t2;
And you'll see the difference disappear. There is no simple fix for this. The problem is not exactly that dynamically invoking code is slow, it is that allowing the jitter optimizer to generate optimal machine code makes it so incredibly fast. Which of course is a feature, not a bug.