C#7.0引入了值元组以及对它们的一些语言级别支持。它们added the support也包含单元素和零元素元组;但是,我找不到任何可行的方案。
通过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)]
通过元组语法:
> 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)]
我认为我找到了this feature was requested所在的线程,但是现在没有代码示例在C#中有效,并且甚至在递归元组模式下都没有在planned features of C# 8.0中找到任何引用。 / p>
在请求线程中提到了功能编程语言。可能有任何功能性语言现在使用它们吗?我不是F#专家,但其元组reference并未提及对单元素和零元素元组的任何使用。
所以TL; DR问题:
Tuple.Create
或构造函数,而是通过本地语言支持。答案 0 :(得分:11)
2元组或3元组表示一组相关项。 (2D空间中的点数,颜色的RGB值等。)1元组不是很有用,因为可以很容易地用单个int
替换它。
0元组似乎毫无用处,因为它绝对不包含任何东西。但是它具有的特性使其在F#等功能语言中非常有用。例如,0元组类型只有一个值,通常表示为()
。所有0元组都具有此值,因此本质上是单例类型。在包括F#在内的大多数函数式编程语言中,这称为unit
类型。
在C#中返回void
的函数将在F#中返回unit
类型:
let printResult = printfn "Hello"
在F#交互式解释器中运行该命令,您将看到:
val printResult : unit = ()
这意味着值printResult
的类型为unit
,并具有值()
(空元组,unit
类型的唯一值)
函数也可以将unit
类型作为参数。在F#中,函数看起来好像没有参数。但实际上,它们只是使用unit
类型的单个参数。此功能:
let doMath() = 2 + 4
实际上等同于:
let doMath () = 2 + 4
也就是说,该函数采用类型为unit
的一个参数并返回int
值6。如果您在定义此函数时查看F#交互式解释器打印的类型签名,会看到:
val doMath : unit -> int
所有函数都将至少使用一个参数并返回一个值,即使该值有时是诸如()
之类的“无用”值这一事实,这意味着F#中的函数组合比语言中的编写容易得多没有unit
类型。但这是一个更高级的主题,稍后我们将介绍。现在,请记住,当您在函数签名中看到unit
或在函数的参数中看到()
时,这就是0元组类型,它表示“此函数接受或返回,没有有意义的值。”
答案 1 :(得分:3)
我想不出一个元素元组的用例。编辑-正如所指出的那样,引用的页面提到了一个元素元组作为命名返回参数的方法,尽管这可能是C#特定的,但这听起来实际上很有用。
零元素元组使用功能语言(也称为unit)。这有点像C#中的void,某些(大多数?)功能语言没有。
区别在于()是一个实际值,您可以使用它来处理诸如保持列表,模式匹配等之类的事情。功能语言需要这样做,因为函数必须返回某些内容,并且如果要返回“ nothing”(无),则表示必须通过返回()显式地执行此操作。您还可以编写一个接受unit作为参数的函数,这基本上意味着它是一个延迟执行的值,最有可能产生副作用:
let x = getFromDb() // will read DB
stream.Flush() // will change state
答案 2 :(得分:1)
在C#中不支持o元组(nople)和1元组(oneple)。
但是,在基类库(BCL)上,为了保持连贯性,以防万一将来有人找到它的用途,这里有ValueTuple
和ValueTuple<T>
。例如,一种语言具有0元组和1元组的构造。
ValueTuple
有一些附加值。来自the documentation:
ValueTuple结构表示没有元素的元组。它主要用于其静态方法,使您可以创建和比较值元组类型的实例,因此很有用。它的帮助器方法使您可以实例化值元组,而不必显式指定每个值元组组件的类型。通过调用其静态的Create方法,可以创建具有零到八个组成部分的值元组。对于具有八个以上组件的值元组,必须调用ValueTuple构造函数。
答案 3 :(得分:0)
目前,ValueTuple'1
仅用于长元组的表示形式,即使1元组没有C#元组语法:ValueTuple<T1, T2, T3, T4, T5, T6, T7, ValueTuple<T8>>
是8元组的基础类型。 / p>
对于0元组和ValueTuple'0
,我们推测它们可能会出现在未来的场景中(如果我没记错的话,可能是一些递归模式)。
答案 4 :(得分:0)
一个 1 元组可以用作围绕可空值的非空包装器。这在尝试添加到字典时很有用,例如:
void Process<TKey>(TKey[] keys)
{
var dict = new Dictionary<TKey, Something>();
var firstKey = keys[0];
dict[firstKey] = new Something();
...
}
如果启用 nullable
将显示警告(创建 dict
时),因为 TKey
可能是可空类型(API 可能愿意接受)和 {{1 }} 不接受 Dictionary<TKey, TValue>
;同时:
null
不会显示警告。
答案 5 :(得分:0)
1-Tuple 可以用作 lambda 的单个参数列表。元组非常适合用作 lambda 参数列表,因为您可以更改它们的结构而不破坏 lambda。您也可以通过这种方式命名 lambda 的参数。但是由于您不能使用 1-Tuple,如果参数数量更改为 1,您必须恢复为常规参数。
例如:
int DoSomething(
Func<(int First, int Second, int Third), int> function
) =>
function((1, 2, 3));
// DOESN'T WORK
int DoSomethingElse(
Func<(int First), int> function
) =>
function((1));
// does work but not as nice
int DoSomethingElse2(
Func<int, int> function
) =>
function(1);