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

Давайте посмотрим на код, сгенерированный 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#-generated не отмечен как sealed?
  • Почему класс F#-generated содержит общедоступные поля, так как F# не позволяет изменяемые закрытия?
  • Почему делает сгенерированный класс F#, имеют конструктора? Это может быть отлично инициализировано с общедоступными полями...
  • Почему класс C#-generated не отмечен как [Serializable]? Также классы, сгенерированные для выражений последовательности F# также, стали [Serializable] и классы для итераторов C# не делают.
25
задан James Wiseman 1 June 2010 в 09:57
поделиться

2 ответа

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

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

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

4
ответ дан 28 November 2019 в 22:00
поделиться

Почему созданный F # класс не помечен как запечатанный?

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

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

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

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

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

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

Дополнительные варианты генерации кода.

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

4
ответ дан 28 November 2019 в 22:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: