F # Неизменное взаимодействие классов - PullRequest
4 голосов
/ 25 января 2011

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

Допустим, мы создаем класс Vector в F #. Vector.X и Vector.Y должны быть переназначены, но возвращать только новый класс Vector. В C # потребуется много усилий, чтобы .WithX (float x) клонировать существующий объект и вернуть новый. Есть ли простой способ сделать это в F #?

Я искал некоторое время, и я не могу найти никаких документов по этому вопросу. Так что любая помощь будет отличной.

И, наконец, если бы я импортировал этот класс в C #, как бы выглядел его интерфейс? Будет ли код F # ограничивать меня от глупостей вроде Vector.X = 10?

Ответы [ 2 ]

8 голосов
/ 25 января 2011

Это будет выглядеть одинаково независимо от того, является ли это C # или F #.

Вы говорите "в C # это займет легкую работу", но я думаю, что cmon

Vector WithX(float x) { return new Vector(x, this.Y); }

это правда?

Как в C #, так и в F #, чтобы предотвратить присвоение свойству X, вы создаете свойство с помощью «getter», но без «setter».

Я думаю, вы делаете все это сложнее, чем оно есть, или, может быть, я неправильно понимаю, о чем вы спрашиваете.

EDIT

Для (я думаю, редкого) случая, когда имеется 20 полей, и вы можете изменить только небольшое их произвольное подмножество, я нашел симпатичный хак, чтобы красиво использовать вместе необязательные параметры F # и C #.

F # Код:

namespace global

open System.Runtime.InteropServices

type Util =
    static member Some<'T>(x:'T) = Some x

type MyClass(x:int, y:int, z:string) =
    new (toClone:MyClass, 
         [<Optional>] ?x, 
         [<Optional>] ?y, 
         [<Optional>] ?z) = 
            MyClass(defaultArg x toClone.X, 
                    defaultArg y toClone.Y, 
                    defaultArg z toClone.Z)
    member this.X = x
    member this.Y = y
    member this.Z = z

F # код клиента:

let a = new MyClass(3,4,"five")
let b = new MyClass(a, y=44)  // clone a but change y

C # код клиента:

var m = new MyClass(3, 4, "five");
var m2 = new MyClass(m, y:Util.Some(44)); // clone m but change y

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

6 голосов
/ 25 января 2011

F # Типы записей имеют встроенный способ делать именно то, что вы просите:

type Vector = {X:float; Y:float}

let v1 = {X=1.; Y=2.}
let v2 = {v1 with X=3.}

Как это взаимодействует с C #, я не уверен (редактировать: см. комментарий Брайана ).

Вектор будет неизменным для любого языка .NET, поскольку X и Y реализованы как методы получения без установщиков.

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