什么是单元素和零元素元组有用?

Gyö*_*zeg 14 c# f# tuples c#-7.0

C#7.0引入了值元组,并为它们提供了一些语言级支持.他们还添加了单元素和零元素元组的支持 ; 但是,当它们有用时,我找不到任何情况.

通过ValueTuple.Create重载,我可以创建任何类型的元组,但C#7.0语法只允许至少两个元素:

Microsoft (R) Roslyn C# Compiler version 2.8.3.62923
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> ValueTuple.Create()
[()]
> ValueTuple.Create(1)
[(1)]
> ValueTuple.Create(1, "x")
[(1, x)]
Run Code Online (Sandbox Code Playgroud)

通过元组语法:

> var t2 = (1, 2);
> var t1 = (1); // t1 is now int (of course)
> ValueTuple<int> t1 = (1);
(1,23): error CS0029: Cannot implicitly convert type 'int' to 'ValueTuple<int>'
> ValueTuple<int> t1 = new ValueTuple<int>(1);
> t1
[(1)]
Run Code Online (Sandbox Code Playgroud)

我想我找到了请求此功能的线程,但现在没有任何代码示例在C#中有效,也无法在C#8.0计划功能中找到任何引用,甚至在递归元组模式中也找不到.

在请求线程中提到了函数式编程语言.是否有任何功能语言,现在使用它们?我不是F#专家,但它的元组引用没有提到任何单元素和零元素元组的使用.

所以TL; DR问题:

  • 在任何(可能是功能性的).NET语言中使用单元素和零元素元组吗?我的意思不是由Tuple.Create构造函数构成,而是由本地语言支持.
  • 它们是否计划在未来版本的C#中使用?
  • 或者它们是否存在"以防万一",以便将来兼容?

rmu*_*unn 10

0元组有什么好处?

2元组或3元组表示一组相关项.(2D空间中的点,颜色的RGB值等)1元组不是很有用,因为它可以很容易地用单个替换int.

0元组似乎更无用,因为它绝对没有任何东西.然而,它具有使其在F#等函数式语言中非常有用的属性.例如,0元组类型只有一个值,通常表示为().所有0元组都有此值,因此它基本上是单例类型.在大多数函数式编程语言中,包括F#,这称为unit类型.

void在C#中返回的函数将返回unitF#中的类型:

let printResult = printfn "Hello"
Run Code Online (Sandbox Code Playgroud)

在F#交互式解释器中运行它,你会看到:

val printResult : unit = ()
Run Code Online (Sandbox Code Playgroud)

这意味着该值printResult是类型unit,并具有值()(空元组,该unit类型的唯一值).

函数也可以将unit类型作为参数.在F#中,函数看起来可能没有参数.但事实上,他们只采用了一种类型的参数unit.这个功能:

let doMath() = 2 + 4
Run Code Online (Sandbox Code Playgroud)

实际上相当于:

let doMath () = 2 + 4
Run Code Online (Sandbox Code Playgroud)

也就是说,一个函数接受一个类型的参数unit并返回int值6.如果你看一下定义这个函数时F#交互式解释器打印的类型签名,你会看到:

val doMath : unit -> int
Run Code Online (Sandbox Code Playgroud)

事实上所有函数将至少获取一个参数并返回一个值,即使该值有时是"无用"值(),这意味着F#中的函数组合比没有该unit类型的语言容易得多.但这是一个更高级的主题,我们将在稍后介绍.现在,请记住,当您unit在函数签名或()函数的参数中看到时,这是0元组类型,用作说"此函数接受或返回没有有意义的值"的方式.

  • PS 我提到的“我们稍后将讨论的更高级的主题”是如何在 F# 中组合*所有* 函数。在 C# 中,你可以编写一个 Compose 方法,它接受一个 `Func&lt;A, B&gt;` 和一个 `Func&lt;B, C&gt;` 并返回一个 `Func&lt;A, C&gt;`。但是 `Action&lt;T&gt;` 会弄乱你的 Compose 方法,你必须编写四个变体:`Compose(Func, Func)`、`Compose(Func, Action)`、`Compose(Action, Func) ` 和 `Compose(Action, Action)`。但是,在 F# 中,您可以只编写一个 Compose 函数,它适用于所有函数:`unit -&gt; unit` 可以与 `unit -&gt; int` 组合,依此类推。 (2认同)