Объявить частные статические члены в F #? - PullRequest
2 голосов
/ 12 апреля 2010

Я решил перенести класс в C # ниже на F # в качестве упражнения.

Это было сложно.Я замечаю только три проблемы

1) Greet является видимым 2) Я не могу получить v в качестве статической переменной класса 3) Я не знаю, как установить член greet в конструкторе.

Как я могу это исправить?Код должен быть достаточно похожим, чтобы мне не нужно было менять исходники C #.Только для банкоматов Test1.v = 21;не работает

C #

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

namespace CsFsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Test1.hi("stu");
            new Test1().hi();
            Test1.v = 21;
            var a = new Test1("Stan");
            a.hi();
            a.a = 9;

            Console.WriteLine("v = {0} {1} {2}", a.a, a.b, a.NotSTATIC());
        }
    }
    class Test1
    {
        public int a;
        public int b { get { return a * 2; } }
        string greet = "User";
        public static int v;

        public Test1() {}
        public Test1(string name) { greet = name; }

        public static void hi(string greet) { Console.WriteLine("Hi {0}", greet); }
        public void hi() { Console.WriteLine("Hi {0} #{1}", greet, v); }
        public int NotSTATIC() { return v; }
    }
}

F #

namespace CsFsTest

type Test1 = 
    (*
        public int a;
        public int b { get { return a * 2; } }
        string greet = "User";
        public static int v;
    *)
    [<DefaultValue>]
    val mutable a : int
    member x.b = x.a * 2
    member x.greet = "User" (*!! Needs to be private *)

    [<DefaultValue>]
    val mutable v : int (*!! Needs to be static *)

    (*
        public Test1() {}
        public Test1(string name) { greet = name; }
    *)
    new () = {}
    new (name) = { }

    (*  
        public static void hi(string greet) { Console.WriteLine("Hi {0}", greet); }
        public void hi() { Console.WriteLine("Hi {0} #{1}", greet, v); }
        public int NotSTATIC() { return v; }
    *)   
    static member hi(greet) = 
        printfn "hi %s" greet
    member x.hi() =
        printfn "hi %s #%i" x.greet x.v
    member x.NotSTATIC() =
        x.v

Ответы [ 3 ]

10 голосов
/ 12 апреля 2010

В языке F # есть некоторые конструкции, которые не имеют эквивалента в C #, но в нем есть почти все, что вы можете использовать в C #. Это означает, что если вы просто переводите код из C # в F #, вы в конечном итоге будете использовать только подмножество F #. В результате иногда лучше искать некоторые конкретные конструкции F #.

Я думаю, что это также относится и к статическим элементам. В дополнение к классам, вы также можете организовать код F # с помощью модулей, которые обеспечивают естественный способ объявления статических данных и функций. Вот пример модуля для приветствия:

// modules are automatically 'static' (from the C# point of viedw)
module Greetings = 
  // public mutable field inside a module
  let mutable how = "Hello "
  // global function that uses the field
  let greet name = 
    Console.WriteLine(how + name)

// modify the global field and invoke global function
Greetings.how <- "Ahoj "
Greetings.greet("Tomas")

Если вам нужны статические функциональные возможности и некоторые функциональные возможности экземпляра, обычно легко разделить функциональные возможности между модулем и стандартным классом. Очевидное преимущество заключается в том, что он упрощает синтаксис, но также может помочь структурировать код:

type Person(name) =
  member GreetMe() = 
    Greetings.greet(name)

Члены внутри модуля могут быть объявлены как private или internal, если вы хотите скрыть их от пользователя. Например, если вы хотите, чтобы поле how было доступно только вашей сборке, вы можете написать:

let mutable internal how = "Hello "  

Я думаю, что это дает вам более идиоматический код F #, поэтому я бы предпочел этот стиль программирования при написании кода F #. Если вы планируете использовать это из C #, то модули будут отображаться как статические классы, которые также просты в использовании.

В качестве дополнительного примечания обычно рекомендуется избегать использования слишком большого количества изменяемых элементов. Тем не менее, если вы используете их для какой-то конфигурации, то я думаю, что все в порядке.

5 голосов
/ 12 апреля 2010

Ниже приведен пример F #, который компилируется с клиентом C #.

В .NET очень редко выставляются открытые поля; Я бы порекомендовал против этого. Синтаксис F # для выставления полей несколько громоздок.

namespace CsFsTest

open System

type Test1 =
    val mutable private greet : string
    [<DefaultValue>]
    val mutable public a : int
    [<DefaultValue>]
    static val mutable private vv : int

    static member v with get() = Test1.vv 
                    and set(x) = Test1.vv <- x

    member this.b = this.a*2
    static member hi(greet:string) = Console.WriteLine("Hi {0}", greet)
    member this.hi() = Console.WriteLine("Hi {0} #{1}", this.greet, Test1.v)

    new() = { greet = "User" }
    new(name : string) = { greet = name }

    member this.NotSTATIC() = Test1.v
2 голосов
/ 12 апреля 2010

Вы определяете приветствие как свойство. Это не обязательно должен быть один.

// these are the same
member x.greet = "User" 
member x.greet with get() = "User"

Это может быть просто переменная.

val mutable private greet : string
new () = { greet = "User" }
new (name) = { greet = name }

F # не позволяет вам иметь публичные статические переменные класса. Вы должны использовать геттер / сеттер.

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