2016-06-02 3 views
6

У меня есть тип, определенный в C# как это:Как использовать перегруженные явные операторы преобразования?

struct F { 
    public static explicit operator F(long value) {} 
    public static explicit operator long(F value) {} 
    public static explicit operator F(double value) {} 
    public static explicit operator double(F value) {} 
    // more conversion operators 
} 

В F #, если я хочу, чтобы создать его из длинных, единственный способ, которым я нашел это:

let l = F.op_Explicit 3L 

Я попытался создать строковый чтобы сделать это лучше:

let inline f a = F.op_Explicit a 

Но это не скомпилировано. Я также попытался с ограничением элемента:

let inline f (x:^a) = (F: (static member op_Explicit : ^a -> F) x) 

И это тоже не скомпилировано.

Можно ли определить функцию или оператор для выбора правильной перегрузки?

На стороне записки, он работает хорошо в противоположном направлении:

let f = someF |> int64 // calls the right conversion operator 

ответ

4

Это не действует, чтобы иметь ограничение члена на один конкретный тип; Однако, это может работать для вас:

let inline f (x:^a) : F = 
    let inline g x = ((^b or ^c):(static member op_Explicit : ^b -> ^c) x) 
    g x 

Это имеет более общий тип f : ^a -> F when (^a or F) : (static member op_Explicit : ^a -> F), который является типом, который невозможно вручную аннотировать любое значение с!

+0

Отлично! Меня беспокоит только предупреждение: «Ограничения членов с именем« op_Explicit »получают специальный статус компилятором F #, поскольку определенные типы .NET неявно дополняются этим членом. Это может привести к сбоям во время выполнения, если вы пытаетесь вызвать ограничение члена из вашего собственного кода ». Могу ли я его игнорировать? – Asik

+1

@Asik - В этом случае вы можете его игнорировать. Это ограничение применяется в некоторых случаях, когда компилятор действует так, как будто существует op_Explicit, хотя на самом деле его нет. Например, если вы извлекаете 'g' из моего ответа в свое собственное определение, вызов' (g 1: int64) 'будет компилироваться (потому что компилятор делает вид, что существует явное преобразование из int в int64), но будет терпеть неудачу во время выполнения (потому что в действительности такого участника нет, конверсия обычно обрабатывается самой средой исполнения). – kvb

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