Почему test4 и test6 намного медленнее, чем их версия делегата? Я также заметил, что Resharper специально прокомментировал версию делегата, предложив изменить test5 и test7 на «Covert to method group». Что такое test4 и test6, но на самом деле они медленнее?
Вы получите большую подсказку, добавив
Debug.Print(ReferenceEquals(list[0], list[1]) ? "same" : "different");
до конца каждого метода.
С версией делегата Func
компилируется немного, как это было на самом деле:
var func = Func<CacheDependency> <>_hiddenfieldwithinvalidC#name;
if (func == null)
{
<>_hiddenfieldwithinvalidC#name = func = () => p.GetDep();
}
Хотя с группой методов она компилируется почти так же, как:
func = new Func<CacheDependency>(p.GetDep());
Эта памятка часто делается для делегатов, созданных из лямбда-выражений, когда компилятор может определить, что это безопасно, но не для групп методов, передаваемых делегатам, и различия в производительности, которые вы видите, показывают, почему.
Мне кажется, что при вызовах test4 и test6 не наблюдается существенной разницы в производительности, разве статические вызовы не должны быть всегда быстрее?
Не обязательно. В то время как статический вызов имеет преимущество в меньшем количестве передаваемых аргументов (так как нет неявного аргумента this
), это различие:
- Не много для начала.
- Может быть сброшено, если
this
не используется.
- Может быть оптимизировано так, что регистр с указателем
this
перед вызовом является регистром с указателем this
после вызова, поэтому на самом деле не нужно ничего делать, чтобы получить его там.
- Эх, что-то еще. Я не утверждаю, что этот список является исчерпывающим.
На самом деле выигрыш в производительности от статики заключается в том, что если вы будете делать то, что естественно статично в методах экземпляра, вы можете получить чрезмерную передачу объектов, которые на самом деле не нужны и тратят время. Тем не менее, если вы делаете то, что является естественным экземпляром в статических методах, вы можете в конечном итоге хранить / извлекать и / или размещать и / или передавать объекты в аргументах, которые вам не понадобятся, и все будет так же плохо.