在F#中声明私有静态成员?

2 c# f# class

我决定将下面的C#中的课程移植到F#作为练习.

这个很难.我只注意到三个问题

1)问候是可见的2)我不能让v成为静态类变量3)我不知道如何在构造函数中设置greet成员.

我该如何解决这些问题?代码应该足够相似,我不需要更改任何C#源代码.ATM仅限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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 10

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")
Run Code Online (Sandbox Code Playgroud)

如果您需要一些静态功能和一些实例功能,通常很容易在模块和标准类之间拆分功能.显而易见的好处是它为您提供了更简单的语法,但它也可以帮助构建代码:

type Person(name) =
  member GreetMe() = 
    Greetings.greet(name)
Run Code Online (Sandbox Code Playgroud)

模块内的成员可以声明为private或者internal如果要将它们隐藏在用户之外.例如,如果您只想使how您的程序集可以访问该字段,您可以编写:

let mutable internal how = "Hello "  
Run Code Online (Sandbox Code Playgroud)

我认为这给你提供了更多惯用的F#代码,所以在编写F#代码时我可能更喜欢这种编程风格.如果您打算在C#中使用它,那么模块将显示为静态类,这些类也很容易使用.

作为附注,通常建议避免使用太多可变成员.但是,如果您正在使用它们进行某种配置,那么我认为它没问题.


Bri*_*ian 5

下面是一些针对C#客户端编译的F#.

在.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
Run Code Online (Sandbox Code Playgroud)