Генерация кода лямбда-выражений в C # и F # - PullRequest
25 голосов
/ 01 июня 2010

Давайте посмотрим на код, сгенерированный F # для простой функции:

let map_add valueToAdd xs =
    xs |> Seq.map (fun x -> x + valueToAdd)

Сгенерированный код для лямбда-выражения (экземпляр функционального значения F #) будет выглядеть так:

[Serializable]
internal class map_add@3 : FSharpFunc<int, int> {
    public int valueToAdd;
    internal map_add@3(int valueToAdd) { this.valueToAdd = valueToAdd; }
    public override int Invoke(int x)  { return (x + this.valueToAdd); }
}

И посмотрите почти на тот же код C #:

using System.Collections.Generic;
using System.Linq;

static class Program {
    static IEnumerable<int> SelectAdd(IEnumerable<int> source, int valueToAdd) {
        return source.Select(x => x + valueToAdd);
    }
}

И сгенерированный код для лямбда-выражения C #:

[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
    public int valueToAdd;
    public int <SelectAdd>b__0(int x) { return (x + this.valueToAdd); }
}

Итак, у меня есть несколько вопросов:

  • Почему класс, генерируемый F #, не помечен как sealed?
  • Почему класс, генерируемый F #, содержит публичные поля, поскольку F # не допускает изменяемых замыканий?
  • Почему созданный класс F # имеет конструктор? Может быть отлично инициализирован с открытыми полями ...
  • Почему класс, сгенерированный в C #, не помечен как [Serializable]? Также классы, сгенерированные для выражений последовательности F #, также стали [Serializable], а классы для итераторов C # - нет.

Ответы [ 2 ]

4 голосов
/ 01 июня 2010

Почему класс, генерируемый F #, не помечен как запечатанный?

Поскольку компилятор этого не делает (это, в конце концов, выбор генерации кода.

Почему класс, генерируемый F #, содержит открытые поля, поскольку F # не допускает непостоянных замыканий?

Вы должны иметь возможность получить ссылку на экземпляр, чтобы изменить его. Но вы не можете, поэтому изменчивость не имеет значения. И, вероятно, это исключает необходимость в особом случае, когда изменяемый объект захватывается в замыкании.

Почему у сгенерированного F # класса есть конструктор? Может быть отлично инициализирован с открытыми полями ...

Опять выбор генерации кода.

Почему класс, сгенерированный в C #, не помечен как [Сериализуемый]? Также классы, сгенерированные для выражений последовательности F #, также стали [Serializable], а классы для итераторов C # - нет.

Больше вариантов генерации кода.

Ни один из этих вариантов не виден разработчику (т. Е. Не имеет значения для клиентского кода), он действительно не имеет значения.

4 голосов
/ 01 июня 2010

Поскольку они генерируются компилятором, проблемы запечатанных / открытых полей немного спорны - вы никогда не должны видеть это, кроме как с помощью инструментов отладки - как бы вы создали подклассы или изменили его, кроме как обходя компилятор? Если у вас есть этот уровень отладочного доступа, вы можете изменить его в любом случае (через отражение).

Для C # необходимо, чтобы top был полем , чтобы разрешить определенное ref / out использование и разрешить правильное использование с захваченными изменяемыми структурами (да, мы знаем, зло). Я предполагаю, что F # здесь аналогичен (можете ли вы изменить элемент sub [[sub- [sub -]] захваченного значения?). Члены, вероятно, могут быть внутренними.

Re [Serialziable]; почему то, что лежит в основе замыкания, может быть сериализуемым? Делегаты делают крайне плохих кандидатов на сериализацию. Возможно, природа F # означает, что он лучше подходит для сохранения операции (среднего потока) на диске - но в целом я бы не рекомендовал это делать. Я не ожидал бы, что эти объекты (итераторы и классы захвата) будут сериализуемыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...