Мне любопытно на предмет улучшений производительности, которые были сделаны для FSharpFunc <>. Действительно ли это - то, что это не содержит, несколько делегируют, таким образом, нет никакой потребности циклично выполниться по всем ссылкам при увольнении вызова функции? Что-либо еще?
Я думаю, что первичная мотивация к использованию FSHARPFUNC <>
, а не FUNC <>
или любого другого делегата заключается в том, что вы не можете создать класс, который будет наследуться от типа делегата ( Сначала это звучит разумно, но в .NET, делегат на самом деле просто какой-то специальный класс, поэтому может быть в принципе возможно, чтобы позволить этому). Почему это нужно?
Если вы пишете функцию в f #, то она (в относительно немногих, но вполне важных случаях) обрабатывается в форме Curry. Например int -> int -> int
на самом деле находится тип функции int -> (int -> int)
(Carrying означает, что вы пишете функцию с использованием только функций одного параметра - Если вы назовите это с первым аргументом, вы получите функцию в результате, и вы можете вызвать возвращенную функцию со вторым аргументом).
Если F # использовал делегаты, тип будет что-то вроде Функна
. Как упомянул Брайан, вызов F X Y
будет переведен на два вызова: F (x) (y)
. Этот вид вызова, однако, является наиболее распространенным (указание всего одного аргумента приложение частичной функции ). Итак, когда F # компилирует такую функцию, она создает унаследованный класс с оптимизированным методом invoke, чтобы его можно было вызвать как f.invoke (x, y)
:
class @some_F#_name@ : Func<int, Func<int, int>> {
public int Invoke(int arg1, int arg2) { /* optimized call */ }
}
К сожалению, это не Вы можете создать такой класс, наследующуюся из стандарта Func
(потому что это делегат), поэтому F # должен объявить свой собственный тип, который можно использовать в качестве базового класса ...
Если я звоню «Метод ()», что происходит с объектом MyClass, который был создан в процессе?
Это создается на кучи GC. Тогда ссылка на его местоположение в куче помещается на стек. Тогда происходит звонок к другому Method. Затем называется метод ToString объекта, и результат напечатан. Тогда krymethod возвращается.
Это все еще существует в стеке после вызова, хотя это ничего не использует?
Ваш вопрос неоднозначен. По «вызову» вы имеете в виду вызов методу или другому Method? Это имеет значение, потому что на данный момент, является ли память кучи кандидатом для сборки мусора, зависит от того, скомпилированы ли вы с включенными или выключенными оптимизациями. Я собираюсь немного изменить свою программу, чтобы проиллюстрировать разницу. Предположим, что у вас есть:
void Method()
{
AnotherMethod(new MyClass());
Console.WriteLine("Hello world");
}
с выключенным оптимизациями, мы иногда на самом деле генерируем код, который будет похож на это:
void Method()
{
var temp = new MyClass();
AnotherMethod(temp);
Console.WriteLine("Hello world");
}
в неоптимизированной версии, время выполнения будет фактически выбрать для лечения объекта, как не подходит, пока метод не возвращается, после возврата метода Отказ В оптимизированной версии время выполнения может выбрать для обработки объекта как коллекционируемых, как только oneMethod возвращается, перед WriteLine.
Причина разницы заключается в том, что создание жизни объекта более предсказуемой во время сеансов отладки часто помогает людям понять их программы.
Или это удалено немедленно?
Ничто не собирается сразу; Коллектор мусора бежит, когда ощущается, как он должен бежать. Если вам нужен какой-либо ресурс, такой как файловый дескриптор, который следует сразу убирать, когда вы закончите, затем используйте блок «Использование». Если нет, то пусть сборщик мусора решается, когда собирать память.
Должен ли я установить его на NULL, чтобы получить GC, чтобы заметить его быстрее?
Вам нужно установить Что к нулю? Какую переменную вы имели в виду?
Независимо от того, вы не имеют , чтобы сделать все, чтобы сделать работу сборщики мусора. Он проходит самостоятельно, просто хорошо, не вызывая вас.
Я думаю, что вы перевыпите эту проблему. Пусть сборщик мусора делает свое дело и не подчеркивает об этом. Если у вас есть реальная проблема с памятью, не собираться своевременно, то покажи нам какой-то код, который иллюстрирует эту проблему; В противном случае просто расслабьтесь и научитесь любить автоматическое утилизацию хранения.
-121--3545712- (Я думаю, что теперь они называются FSHARPFUNC
, а не FastFunc
.)
Он представлен как тип с одним абстрактным методом ( Вызвать), что я думаю, избегает некоторых накладных расходов, которые вы получаете с настоящими делегатами. И для нескольких параметров Curry Curry позволяет вам позвонить со всеми параметрами «сразу», а не один-по-либо (например, так, чтобы FXY
можно вызывать на CLR CLR как F (x , y)
, а не f (x) (y)
.
. FS в FSHARP.CORE в исходном распределении, который поставляется с выпуском CTP.