当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在C#7中,可以将元组解构为方法参数》经验,为你挑选了2个好方法。

比如我有

private void test(Action> fn)
{
    fn(("hello", 10));
}

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

我想写这样的东西

private void test(Action> fn)
{
    fn(("hello", 10));
}

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

这有可能用一些正确的表示法吗?



1> Paulo Morgad..:

您可以将其缩短为:

void test( Action> fn)
{
    fn(("hello", 10));
}

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

希望有一天我们可以将参数从元组映射到方法调用:

void test(Action> fn)
{
    fn(@("hello", 10)); // <-- made up syntax
}

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

但目前还没有.


fn(@(“ hello”,10));`没有意义。它仍在向该函数传递一个元组,因此只要`fn((“ hello”,10));`就足够了。我们不需要任何特殊的语法,只需要更好的类型推断即可。试想一下最简单的`test((((str,inte))=>`),它将表明(str,inte)是单个未命名的元组类型参数。未命名的参数允许将`str`和`inte`视为特殊名称。从传入的元组解构的局部自动变量,与`test((((string,int)p)=>`)不同,在这里,parameter是名称,(string,int)是具有字段Item1,Item2的给定类型的非元组。

2> Glenn Slayde..:

I.具有distingle-args单个n元组参数的Action/ Func委托示例:

// 1. Action with 3 distinct 'int' parameters
Action ArgsAction = (i1, i2, i3) => i1 += i2 += i3;

// 2. Func with 3 distinct 'int' parameters, returning 'long'
Func 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;

二。演示直接使用上述示例

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.

下两节中的示例以其各自的非本地参数形式调用委托。要延迟方法调用或保留适合的委托以进行缓存或延迟/多次调用,请参见VI。和VII。

三,将元组分散(“ splat”)到多参数方法中。

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

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

IV。将不同的args传递给采用元组的方法:

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

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

V.扩展方法ScatterGather在上文(III)和(IV)中使用:

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

// disperse n-tuple into Func arguments
public static TResult Scatter(in this (T0 i0, T1 i1) t, Func f) => f(t.i0, t.i1);
public static TResult Scatter(in this (T0 i0, T1 i1, T2 i2) t, Func f) => f(t.i0, t.i1, t.i2);
public static TResult Scatter(in this (T0 i0, T1 i1, T2 i2, T3 i3) t, Func 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(this Action<(T0, T1)> a, T0 i0, T1 i1) => a((i0, i1));
public static void Gather(this Action<(T0, T1, T2)> a, T0 i0, T1 i1, T2 i2) => a((i0, i1, i2));
public static void Gather(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(this Func<(T0, T1), TResult> f, T0 i0, T1 i1) => f((i0, i1));
public static TResult Gather(this Func<(T0, T1, T2), TResult> f, T0 i0, T1 i1, T2 i2) => f((i0, i1, i2));
public static TResult Gather(this Func<(T0, T1, T2, T3), TResult> f, T0 i0, T1 i1, T2 i2, T3 i3) => f((i0, i1, i2, i3));

VI。奖金回合。如果您打算以其备用格式多次调用元组或与众不同的参数的委托,或者还没有准备好实际调用它,则可能希望从元组采用的形式显式地预先转换委托给等效的distingle-args委托,反之亦然。您可以缓存转换后的委托,以供以后多次重复使用。

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.

七。VI中显示的奖金示例的扩展方法。

// convert tuple-taking Action delegate to distinct-args form
public static Action ToScattered(this Action<(T0, T1)> a) => (i0, i1) => a((i0, i1));
public static Action ToScattered(this Action<(T0, T1, T2)> a) => (i0, i1, i2) => a((i0, i1, i2));
public static Action ToScattered(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 ToScattered(this Func<(T0, T1), TResult> f) => (i0, i1) => f((i0, i1));
public static Func ToScattered(this Func<(T0, T1, T2), TResult> f) => (i0, i1, i2) => f((i0, i1, i2));
public static Func ToScattered(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(this Action a) => t => a(t.Item1, t.Item2);
public static Action<(T0, T1, T2)> ToGathered(this Action a) => t => a(t.Item1, t.Item2, t.Item3);
public static Action<(T0, T1, T2, T3)> ToGathered(this Action 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(this Func f) => t => f(t.Item1, t.Item2);
public static Func<(T0, T1, T2), TResult> ToGathered(this Func f) => t => f(t.Item1, t.Item2, t.Item3);
public static Func<(T0, T1, T2, T3), TResult> ToGathered(this Func f) => t => f(t.Item1, t.Item2, t.Item3, t.Item4);

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有