首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C# 7中,是否可以将元组解构为方法参数?

在C# 7中,是否可以将元组解构为方法参数?
EN

Stack Overflow用户
提问于 2017-01-11 11:20:02
回答 6查看 29.5K关注 0票数 53

例如,我有

代码语言:javascript
复制
private void test(Action<ValueTuple<string, int>> fn)
{
    fn(("hello", 10));
}

test(t => 
 {
    var (s, i) = t;
    Console.WriteLine(s);
    Console.WriteLine(i);
});

我想写这样的东西

代码语言:javascript
复制
private void test(Action<ValueTuple<string, int>> fn)
{
    fn(("hello", 10));
}

test((s,i) => 
{
    Console.WriteLine(s);
    Console.WriteLine(i);
});

这有可能用适当的符号表示吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-01-11 11:48:05

你可以把它缩短到:

代码语言:javascript
复制
void test( Action<ValueTuple<string, int>> fn)
{
    fn(("hello", 10));
}

test(((string s, int i) t) =>
{
    Console.WriteLine(t.s);
    Console.WriteLine(t.i);
});

希望有一天我们能够将参数从元组拆分到方法调用:

代码语言:javascript
复制
void test(Action<ValueTuple<string, int>> fn)
{
    fn(@("hello", 10)); // <-- made up syntax
}

test((s, i) =>
{
    Console.WriteLine(s);
    Console.WriteLine(i);
});

但现在不行。

票数 37
EN

Stack Overflow用户

发布于 2018-08-25 09:57:18

I. Action /Func委托的示例,它们具有distinct args vs. single n-tuple参数:

代码语言:javascript
复制
// 1. Action with 3 distinct 'int' parameters
Action<int, int, int> ArgsAction = (i1, i2, i3) => i1 += i2 += i3;

// 2. Func with 3 distinct 'int' parameters, returning 'long'
Func<int, int, int, long> ArgsFunc = (i1, i2, i3) => (long)i1 + i2 + i3;

// 3. Action with a single 3-tuple parameter
Action<(int, int, int)> TupleAction = args => args.Item1 += args.Item2 += args.Item3;

// 4. Action with a single 3-tuple parameter, returning 'long'
Func<(int, int, int), long> TupleFunc = args => (long)args.Item1 + args.Item2 + args.Item3;

II.演示了上述示例的直接用法。

代码语言:javascript
复制
long r;

// pass distinct params to multi-arg methods

ArgsAction(1, 2, 3);                // 1.

r = ArgsFunc(1, 2, 3);              // 2.

// pass tuple to tuple-taking methods

TupleAction((1, 2, 3));             // 3.

r = TupleFunc((1, 2, 3));           // 4.

下面两个部分中的示例以各自的非本机参数形式调用委托。若要延迟方法调用或保留用于缓存或延迟/多次调用的代理,请参见VII和VII。

III.分散("splat")将一个元组分成多个arg方法.

代码语言:javascript
复制
(1, 2, 3).Scatter(ArgsAction);      // 1.

r = (1, 2, 3).Scatter(ArgsFunc);    // 2.

IV.将不同的args传递给元组方法:

代码语言:javascript
复制
TupleAction.Gather(1, 2, 3);        // 3.

r = TupleFunc.Gather(1, 2, 3);      // 4.

V.扩展方法(III)和(IV)中使用的ScatterGather

代码语言:javascript
复制
// disperse n-tuple into Action arguments
public static void Scatter<T0, T1>(in this (T0 i0, T1 i1) t, Action<T0, T1> a) => a(t.i0, t.i1);
public static void Scatter<T0, T1, T2>(in this (T0 i0, T1 i1, T2 i2) t, Action<T0, T1, T2> a) => a(t.i0, t.i1, t.i2);
public static void Scatter<T0, T1, T2, T3>(in this (T0 i0, T1 i1, T2 i2, T3 i3) t, Action<T0, T1, T2, T3> a) => a(t.i0, t.i1, t.i2, t.i3);

// disperse n-tuple into Func arguments
public static TResult Scatter<T0, T1, TResult>(in this (T0 i0, T1 i1) t, Func<T0, T1, TResult> f) => f(t.i0, t.i1);
public static TResult Scatter<T0, T1, T2, TResult>(in this (T0 i0, T1 i1, T2 i2) t, Func<T0, T1, T2, TResult> f) => f(t.i0, t.i1, t.i2);
public static TResult Scatter<T0, T1, T2, T3, TResult>(in this (T0 i0, T1 i1, T2 i2, T3 i3) t, Func<T0, T1, T2, T3, TResult> f) => f(t.i0, t.i1, t.i2, t.i3);

// accumulate 'n' distinct args and pass into Action as an n-tuple
public static void Gather<T0, T1>(this Action<(T0, T1)> a, T0 i0, T1 i1) => a((i0, i1));
public static void Gather<T0, T1, T2>(this Action<(T0, T1, T2)> a, T0 i0, T1 i1, T2 i2) => a((i0, i1, i2));
public static void Gather<T0, T1, T2, T3>(this Action<(T0, T1, T2, T3)> a, T0 i0, T1 i1, T2 i2, T3 i3) => a((i0, i1, i2, i3));

// accumulate 'n' distinct args and pass into Func as an n-tuple
public static TResult Gather<T0, T1, TResult>(this Func<(T0, T1), TResult> f, T0 i0, T1 i1) => f((i0, i1));
public static TResult Gather<T0, T1, T2, TResult>(this Func<(T0, T1, T2), TResult> f, T0 i0, T1 i1, T2 i2) => f((i0, i1, i2));
public static TResult Gather<T0, T1, T2, T3, TResult>(this Func<(T0, T1, T2, T3), TResult> f, T0 i0, T1 i1, T2 i2, T3 i3) => f((i0, i1, i2, i3));

VI.奖金回合.如果您计划以它的替代形式多次调用元组或不同的接受arg委托,或者如果您还没有准备好实际调用它,您可能希望显式地预先将委托从tuple-taking表单转换为等效的distinct args委托,反之亦然。您可以缓存转换后的委托,以便在以后进行多次或任意重用。

代码语言:javascript
复制
var ga = ArgsAction.ToGathered();        // 1.
// later...
ga((1, 2, 3));
// ...
ga((4, 5, 6));

var gf = ArgsFunc.ToGathered();          // 2.
// later...
r = gf((1, 2, 3));
// ...
r = gf((4, 5, 6));

var sa = TupleAction.ToScattered();      // 3.
// later...
sa(1, 2, 3);
// ...
sa(4, 5, 6);

var sf = TupleFunc.ToScattered();        // 4.
// later...
r = sf(1, 2, 3);
// ...
r = sf(4, 5, 6);

// of course these approaches also supports in-situ usage:

ArgsAction.ToGathered()((1, 2, 3));      // 1.
r = ArgsFunc.ToGathered()((1, 2, 3));    // 2.

TupleAction.ToScattered()(1, 2, 3);      // 3.
r = TupleFunc.ToScattered()(1, 2, 3);    // 4.

VII.第六章中所示奖金示例的扩展方法。

代码语言:javascript
复制
// convert tuple-taking Action delegate to distinct-args form
public static Action<T0, T1> ToScattered<T0, T1>(this Action<(T0, T1)> a) => (i0, i1) => a((i0, i1));
public static Action<T0, T1, T2> ToScattered<T0, T1, T2>(this Action<(T0, T1, T2)> a) => (i0, i1, i2) => a((i0, i1, i2));
public static Action<T0, T1, T2, T3> ToScattered<T0, T1, T2, T3>(this Action<(T0, T1, T2, T3)> a) => (i0, i1, i2, i3) => a((i0, i1, i2, i3));

// convert tuple-taking Func delegate to its distinct-args form
public static Func<T0, T1, TResult> ToScattered<T0, T1, TResult>(this Func<(T0, T1), TResult> f) => (i0, i1) => f((i0, i1));
public static Func<T0, T1, T2, TResult> ToScattered<T0, T1, T2, TResult>(this Func<(T0, T1, T2), TResult> f) => (i0, i1, i2) => f((i0, i1, i2));
public static Func<T0, T1, T2, T3, TResult> ToScattered<T0, T1, T2, T3, TResult>(this Func<(T0, T1, T2, T3), TResult> f) => (i0, i1, i2, i3) => f((i0, i1, i2, i3));

// convert distinct-args Action delegate to tuple-taking form
public static Action<(T0, T1)> ToGathered<T0, T1>(this Action<T0, T1> a) => t => a(t.Item1, t.Item2);
public static Action<(T0, T1, T2)> ToGathered<T0, T1, T2>(this Action<T0, T1, T2> a) => t => a(t.Item1, t.Item2, t.Item3);
public static Action<(T0, T1, T2, T3)> ToGathered<T0, T1, T2, T3>(this Action<T0, T1, T2, T3> a) => t => a(t.Item1, t.Item2, t.Item3, t.Item4);

// convert distinct-args Func delegate to its tuple-taking form
public static Func<(T0, T1), TResult> ToGathered<T0, T1, TResult>(this Func<T0, T1, TResult> f) => t => f(t.Item1, t.Item2);
public static Func<(T0, T1, T2), TResult> ToGathered<T0, T1, T2, TResult>(this Func<T0, T1, T2, TResult> f) => t => f(t.Item1, t.Item2, t.Item3);
public static Func<(T0, T1, T2, T3), TResult> ToGathered<T0, T1, T2, T3, TResult>(this Func<T0, T1, T2, T3, TResult> f) => t => f(t.Item1, t.Item2, t.Item3, t.Item4);
票数 6
EN

Stack Overflow用户

发布于 2017-06-11 19:12:46

查看您的请求有两种方法,但在C# 7.0中都不支持这两种方法。

  • 一种是将元组划分为参数:用元组调用方法,并将元组的元素拆分为该方法的不同参数。您现在可以通过调用M(tuple.first, tuple.second)手动完成此操作。
  • 另一种是对lambda参数的解构:当用参数调用lambda时,将这些参数解构为元素,并在lambda体中使用这些元素。现在,您可以通过将lambda定义为x => { var (first, second) = x; Write(first); Write(second); }来手动完成此操作。

在csharplang设计回购中有一些建议正在讨论中。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41589540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档