2010-04-11 4 views
2

Я решил перенести класс на C# ниже на F # в качестве упражнения.Объявлять частные статические члены в F #?

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

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

Как это исправить? Код должен быть достаточно схожим, чтобы мне не нужно было менять какой-либо источник 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; } 
    } 
} 

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 

ответ

5

Ниже приведено 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

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

// 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 # не позволяет публиковать переменные статического класса. Вы должны использовать геттер/сеттер.

+1

Вы можете скрыть элементы модуля F #, используя файл .fsi, что делает их функционально идентичными частным статическим функциям. – Juliet

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") 

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

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

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

let mutable internal how = "Hello " 

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

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

+0

Прямо сейчас я использую их только так, чтобы я знал, что могу использовать их, если мне нужно. Как вы можете сказать, класс в основном бесполезен, делая разные вещи, так что это может перепутать меня с gotchas. Я почти ушел, пока не добрался до меня. – 2010-04-12 00:54:28

+0

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

Смежные вопросы