![](/img/trans.png)
[英]Is there a less verbose (as in F#) alternative to C# for .NET and imperative OO?
[英]OO alternative to polymorphism in F# when calling F# from C#
我想創建一個庫,它將使用用戶定義的函數創建對象,並使用另一個用戶定義的函數進行修改。
我有一個OCaml背景,看到一個相當簡單的方法來實現它:
//user side
type userType = { mutable time : float }
let userInitialization () = { time = 0. }
let userModification t = t.time <- t.time+1.
//my side
let algo initialization modification n =
let a = Array.init n (fun _ -> initialization ())
modification a.[0]
a
問題是我希望從C#中輕松調用該庫:將函數作為參數可能是一個壞主意。
接口和抽象類(將由userType
繼承)似乎是通常的OO解決方案,但如果我不知道(尚未定義的)userType在我的函數內部進行初始化步驟,則無法初始化對象。
我能想到的唯一解決方法是向用戶詢問他的userType
實例作為用於調用初始化的參數,但這似乎非常不優雅。
有沒有辦法解決這個問題?
您可以定義這樣的界面:
type IInitAndModify<'T> =
abstract member CreateNew : unit -> 'T
abstract member Modify : item : 'T -> unit
也許還有一個用戶可以用來將它傳遞給你的實現的對象:
type Algo<'T> () =
member this.Execute (initAndModify : IInitAndModify<'T>, n) =
algo initAndModify.CreateNew initAndModify.Modify n
從C#開始,它看起來像這樣:
public interface IInitAndModify<T>
{
T CreateNew();
void Modify(T item);
}
public class Algo<T>
{
public Algo();
public T[] Execute(IInitAndModify<T> initAndModify, int n);
}
客戶端開發人員可以像這樣使用它:
public class UserType
{
public float Time { get; set; }
}
public class UserInitAndModify : IInitAndModify<UserType>
{
public UserType CreateNew()
{
return new UserType { Time = 0 };
}
public void Modify(UserType item)
{
item.Time++;
}
}
並寫一個這樣的程序:
static void Main(string[] args)
{
var a = new Algo<UserType>();
var values = a.Execute(new UserInitAndModify(), 10);
foreach (var v in values)
Console.WriteLine(v.Time);
}
運行上面的Main
方法時,輸出如下:
1
0
0
0
0
0
0
0
0
0
Press any key to continue . . .
我傾向於拒絕你不應該在暴露給C#的庫中公開函數作為參數的想法,這樣做變得非常普遍,你只需要看看LINQ,TPL等等。我不會想太多C#開發人員會因此而害怕。
但是,我建議你避免使用帶有cur的參數向C#公開函數,因為這些函數根本不方便使用。
您可以非常輕松地將算法包裝在一個接受tupled形式的參數的函數中,並將System.Func
和System.Action
公開給C#。
let csAlgo (initialisationFunc : System.Func<'a>,
modificationFunc : System.Action<'a>,
n : int) =
algo (initialisationFunc.Invoke) (modificationFunc.Invoke) n
在C#中你可以這樣做:
var res = Module.csAlgo(() => new UserType(0), t => t.Time = t.Time + 1, 16);
另外,您還可以使用CompiledName
屬性來獲得每種語言的套管約定。 標記你的功能
[<CompiledName("ExampleFunction")>]
let exampleFunction () = 1
然后在C#中,它看起來像這樣:
var num = Module.ExampleFunction();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.