65.9K
CodeProject 正在变化。 阅读更多。
Home

元组介绍

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.93/5 (27投票s)

2010年10月26日

CPOL

4分钟阅读

viewsIcon

53302

downloadIcon

125

本文将介绍在 C#4.0 中使用 Tuple 的一些好处。

引言

C#4.0 引入了一个新特性,称为 Tuple(元组)。

定义

在数学和计算机科学中,元组是元素的有序列表。 在集合论中,(有序)n 元组是 n 个元素的序列(或有序列表),其中 n 是一个正整数。 还有一个 0 元组,一个空序列。(来自维基百科)

目的

有时我们需要从方法或函数返回多个值。

使用代码

让我们进行一个简单的实验,了解基本算术运算的概念。

让我们首先编写我们的 Calculate 函数

/// Calculate 

private void Calculate(out int add, out int sub,out int mul,out int div)
{
   int num1 = 5;
   int num2 = 4;
   add = num1 + num2;
   sub = num1 - num2;
   mul = num1 * num2;
   div = num1 / num2;
}

旧方法 (Dotnet 3.5 之前)

方法 1:使用 OUT 参数

调用函数如下:

1.jpg

输出如预期:

2.jpg

方法 2:使用 REF 参数

与第一个类似,但将 OUT 更改为 REF

方法 3:使用自定义数据类型

创建一个 CalculateEntity,如下所示:

3.jpg

并修改我们的 Calculate 函数如下:

/// Calculate
private static CalculateEntity Calculate()
{
            CalculateEntity objCalculateEntity = new CalculateEntity();
            int num1 = 5;
            int num2 = 4;
            objCalculateEntity.Add = num1 + num2;
            objCalculateEntity.Sub = num1 - num2;
            objCalculateEntity.Mul = num1 * num2;
            objCalculateEntity.Div = num1 / num2;
            return objCalculateEntity;
}

调用函数现在将是:

4.jpg

 方法 4:新方法 (Dotnet 4.0) - 使用 Tuple

5.jpg

可以看出,使用 Tuple 我们可以以更好、更易读的方式从函数/方法返回多个值。

上面的示例表明元组只返回相同类型的数据类型。

现在让我们看看如何从元组返回不同的数据类型

让我们修改上面的 Calculate 函数,使最后一个参数为 double。

6.jpg

结果符合预期

7.jpg

Tuple 的重载方法

Tuple 有 8 个重载方法,其签名如下:

1-Tuple 或 Singleton (单例)

public static Tuple 
    Create
    (T1 item1);

2-Tuple 或 Pair (对)

public static Tuple 
     Create
     (T1 item1, T2 item2);

3-Tuple 或 Triple (三元组)

public static Tuple 
     Create
     (T1 item1, T2 item2, T3 item3);

4-Tuple 或 Quadruple (四元组)

public static Tuple 
     Create
     (T1 item1, T2 item2, T3 item3, T4 item4);

5-Tuple 或 Quintuple (五元组)

public static Tuple 
     Create
     (T1 item1, T2 item2, T3 item3, T4 item4,
     T5 item5);

6-Tuple 或 SexTuple (六元组)

public static Tuple 
     Create
     (T1 item1, T2 item2, T3 item3, T4 item4, 
     T5 item5, T6 item6);

7-Tuple 或 SepTuple (七元组)

public static Tuple
    Create
    (T1 item1, T2 item2, T3 item3, T4 item4, 
     T5 item5, T6 item6, T7 item7);

8-Tuple 或 Octuple (八元组)

public static Tuple> 
      Create
      (T1 item1, T2 item2, T3 item3, T4 item4, 
       T5 item5, T6 item6, T7 item7, T8 item8);

仔细观察最后一个重载方法,即八元组,可以发现最后一个参数又是元组,这意味着它可以携带另外 8 个项目,并且该过程继续进行。

让我们看看如何使用最后一个重载方法。

在这里,我将构建一个简单的乘法表,它将使用最后一个重载方法。

乘法表函数如下:

8.jpg

我们已经突出显示了第 8 个参数以及如何使用它。

调用函数同样简单

int number = 5;
var tuple = MultiplicationTable(number);

    string format =
    "Multiplcation Table of {0} is" + Environment.NewLine +
    "------------------------------" + Environment.NewLine + Environment.NewLine +
    "{0} * 1     = {1} " + Environment.NewLine +
    "{0} * 2     = {2} " + Environment.NewLine +
    "{0} * 3     = {3} " + Environment.NewLine +
    "{0} * 4     = {4} " + Environment.NewLine +
    "{0} * 5     = {5} " + Environment.NewLine +
    "{0} * 6     = {6} " + Environment.NewLine +
    "{0} * 7     = {7} " + Environment.NewLine +
    "{0} * 8     = {8} " + Environment.NewLine +
    "{0} * 9     = {9} " + Environment.NewLine +
    "{0} * 10    = {10} " + Environment.NewLine;

    string result = string.Format(
    format
    , number
    , tuple.Item1
    , tuple.Item2
    , tuple.Item3
    , tuple.Item4
    , tuple.Item5
    , tuple.Item6
    , tuple.Item7
    , tuple.Rest.Item1
    , tuple.Rest.Item2
    , tuple.Rest.Item3

    );
Console.WriteLine(result);
Console.ReadKey(true);

输出如下:

9.jpg

可以看出,使用它非常简单。

但是,如果我们需要在运行时确定元组上的参数数量怎么办。

这有点棘手,但通过使用反射可以很容易地完成。 让我们来看看

10.jpg

虽然对反射的完整详细介绍不在本文的范围内,但我们将逐步了解代码的作用。

在这一行

Type t = typeof(CSharpDemo.Program);

我们正在获取类的类型,这里是 Program

然后通过使用 InvokeMember,我们正在调用该方法,这里是 MultiplicationTable。 由于它接受一个参数,因此我们在最后一个参数中传递相同的参数。

11.jpg

InvokeMember 返回一个对象,并且在将该对象强制转换为字符串并进行字符串替换后,我们通过逗号 (,) 分割该对象。

然后,通过应用 新的 Enumerable.Zip 扩展方法,其通用签名是 Enumerable .Zip<TFirst,TSecond,TResult>,我们合并两个序列,以便获得所需的显示格式,最后通过使用 Foreach 扩展方法,我们显示所需的结果。

在 Tuple 上创建自定义扩展方法

元组缺少 ItemCount 或 ItemValues 等的亮点。 但我们可以通过使用 Tuple 上的扩展方法来创建它们。 让我们看看如何。

创建一个名为 TupleExtension.cs 的类并编写以下代码

using System;
using System.Linq;
using System.Reflection;

namespace CSharpDemo
{
    public static class TupleExtension
    {
        public static Tuple GetLengthAndMemeberValues(this Tuple targetTuple, string methodName, object[] param)
        {
            //Obtain the type of the class 
            Type t = typeof(CSharpDemo.Program);

            //Create an instance of the class
            object classInstance = Activator.CreateInstance(t);

            //Invoke the method
            object memberValues = t.InvokeMember(methodName, BindingFlags.InvokeMethod, null, classInstance, param);
            
            //Assign the needed value to the target tuple
            targetTuple = new Tuple
                 (ItemCount(memberValues), memberValues);

            return targetTuple;
        }

        /// 
        /// ItemCount
        /// Get the count of the number of items
        /// 
        /// 
        /// int

        public static int ItemCount(object o)
        {
            return o.ToString()
            .Replace("(", string.Empty)
            .Replace(")", string.Empty)
            .Split(',').Count();
        }
        
    }
}

要使用扩展方法,我们可以继续执行如下所述:

Tuple testTuple = new Tuple (0,null);

var resultantTuple = testTuple
                    .GetLengthAndMemeberValues("MultiplicationTable"
                    , new object[] { number });

Console.WriteLine("Number of TupleItems" + resultantTuple.Item1);
Console.WriteLine("Items of Tuple" + resultantTuple.Item2);

输出如下:

12.jpg

结论

在这个简短的教程中,我们尝试解释使用元组的大部分方法,它的用处,以及如何增加元组克服其可能遇到的缺点的功能的扩展方法。 本文还简要概述了新的 Zip 扩展方法及其用法。 我已将示例代码以及本文一起附加。 随意使用并根据您的要求进行修改。

非常感谢您对该主题的评论,以便改进该主题。

感谢阅读本文。

© . All rights reserved.