Я много раз читал, что
Собрания, сгенерированные из F # или любого другого языка .NET, (почти) неразличимы.
Затем я экспериментировал с F # и С# interop на .NET 4 (бета 2). Я создал новое решение и проект С# со следующим классом:
public class MyClass {
public static int Add(int a, int b) { return a + b; }
}
Затем, в проекте F #, после ссылки на проект С#, я попытался:
MyClsas.Add(4, 5) |> printfn "%d" // prints 9 (no kidding!)
Пока все хорошо. Тогда мне пришло в голову другое предложение, которое я прочитал много раз (возможно, в разных книгах):
При передаче аргументов в функции из других библиотек .NET вы используете синтаксис типа ".MethodName(parm1, parm2)", то есть параметры передаются в качестве кортежа.
Добавьте это к чему-то, что я когда-то читал здесь на SO (но не смог найти ссылку на него), на вопрос, где OP пытался создать такое, как [ 4, 5, 6 ]
(когда он имел в виду [4; 5; 6]
):
"Запятая - это оператор создания набора кортежей, поскольку все остальное использует" двоеточие ".
Затем я изменил свой класс на следующее:
public class MyClass {
public static int Add(int a, int b) { return a + b; }
public static int Add(Tuple<int, int> a) { return a.Item1; }
}
Теперь я попытался использовать его на F #:
MyClass.Add(4, 5) |> printf "%d" // prints ... (keep reading!)
Итак, добавив три приведенные выше цитаты, можно сделать вывод, что:
- F # создаст кортеж, когда увидит
(4, 5)
- Затем он вызовет перегрузку
Add(Tuple<int, int>)
- Итак, он напечатает 4
К моему удивлению, напечатано 9. Разве это не интересно?
Что на самом деле происходит здесь? Вышеуказанные цитаты и эти практические наблюдения, похоже, находятся в противоречии. Можете ли вы обосновать F # "рассуждение" и, возможно, укажете на некоторые документы MSDN, если это возможно?
Спасибо!
ИЗМЕНИТЬ
(чтобы добавить дополнительную информацию (из ответа Blindy))
Если вы выполните:
MyClass.Add((4, 5)) |> printfn "%d" // prints 9
F # вызывает перегрузку Add(Tuple<int, int>)
.
Однако, если вы создаете еще один проект F # (например, другую сборку) с этим:
namespace MyFSharpNamespace
type MyFShapClass = class
static member Add x y = x + y
end
Вы можете использовать его на С#, как этот
public static void Main(string[] args) {
MyFSharpNamespace.MyFSharpClass.Add(4, 5);
}
Пока все хорошо. Теперь, когда вы пытаетесь использовать его из F # (из другого проекта, другой сборки), вам нужно сделать:
MyFSharpNamespace.MyFSharpClass.Add 4 5 |> printfn "%d"
Если вы передадите аргументы как (4, 5)
F # не будет компилироваться, потому что Add
есть int -> int -> int
, а не (int * int) -> int
.
Что происходит?!?