返回和使用元组
返回和使用元组
在本指南中,我们将介绍如何在 C# 中创建元组、如何从方法中返回元组以及如何在代码中的其他地方使用它们。在介绍使元组感觉像是一个更集成的语法功能的语言增强功能之前,我们将介绍两种创建元组的旧机制。
元组是在 .NET 4.0 中引入的,最近在 C# 7 中进行了升级,变得更加易于使用。
什么是元组?
为了理解什么是Tuple,我们将从一个简单的程序开始,该程序创建一个Person类,其中包含一个人的姓名、出生日期和年龄。
using System;
namespace tuplesample
{
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Jonathon Pluralsight";
person.DateOfBirth = new DateTime(1991, 07, 27);
person.Age = CalculateAge(person.DateOfBirth);
Console.WriteLine($"{person.Name} was born in {person.DateOfBirth.Year} and is {person.Age} years old");
}
private static int CalculateAge(DateTime dateOfBirth)
{
DateTime now = DateTime.Now;
int age = now.Year - dateOfBirth.Year;
if (now.Month < dateOfBirth.Month || now.Month == dateOfBirth.Month && now.Day < dateOfBirth.Day)
{
age--;
}
return age;
}
}
public class Person
{
public string Name;
public DateTime DateOfBirth;
public int Age;
}
}
这一切都非常简单,但必须创建一个类来保存一组任意项似乎很浪费。让我们重写此代码以改用Tuple。
using System;
namespace tuplesample
{
class Program
{
static void Main(string[] args)
{
Tuple<string, DateTime, int> person = Tuple.Create("Jonathon Pluralsight", new DateTime(1991, 07, 27), CalculateAge(new DateTime(1991, 07, 27)));
Console.WriteLine($"{person.Item1} was born in {person.Item2.Year} and is {person.Item3} years old");
}
private static int CalculateAge(DateTime dateOfBirth)
{
DateTime now = DateTime.Now;
int age = now.Year - dateOfBirth.Year;
if (now.Month < dateOfBirth.Month || now.Month == dateOfBirth.Month && now.Day < dateOfBirth.Day)
{
age--;
}
return age;
}
}
}
Person类已从我们的代码中完全删除,并由 Tuple 替换。显然,这会给我们的代码带来差异;使用Person类,我们可以为不同的属性赋予有意义的名称,并且可以按照我们喜欢的顺序添加属性。如果使用Item1、Item2等,则看起来更麻烦。
我们可以创建具有各种参数的元组(例如 Tuple<int, int> 和参数编号(例如Item1 ),它们反映了我们创建的特定Tuple类中的位置。然而,有一点奇怪,虽然我们可以创建具有非常长的参数数量的元组,但是一旦我们超过 Item7,Item的编号就会重新开始,但前缀是Rest,因此第八项将是Rest.Item1,第九项将是Rest.Item2,依此类推。这样做的原因是因为Tuple类的实现数量有限; 通过使用这种Rest方法,设计人员允许开发人员尽可能多地灵活,而不会设置硬性限制。对于简单类型,每个 Item 的值都是固定的。如果我们想改变它们,我们必须重新创建 Tuple 。这意味着我们不能做person.Item1 = "Fred Olson";例如。
此时,您可能想知道为什么我们需要一个Tuple。通常,我倾向于在以下三种情况之一中使用元组:
- 当我想从异步方法返回多个值时。
- 当我想避免在方法中使用多个输出参数时。
- 当我想将多个值包装在一起并传递到诸如Thread.Start之类的方法中时。
返回元组
从方法中返回Tuple很简单。让我们将上面的示例代码更改为在其自己的方法中创建Tuple,如下所示:
private static Tuple<string, DateTime, int> GetPerson()
{
DateTime dateOfBirth = new DateTime(1991, 07, 27);
return Tuple.Create("Jonathon Pluralsight", dateOfBirth, CalculateAge(dateOfBirth));
}
我们将人口改为
Tuple<string, DateTime, int> person = GetPerson();
让代码更简单
此类代码的最大问题之一是它看起来很麻烦,当我们尝试查看包含它的代码时,它可能会导致中断。当 C# 7 发布时,引入了一种新的元组类型: ValueTuple 。 ValueTuples 是一组与Tuple类类似的泛型类,但此功能背后的团队借此机会增强了语言,以简化创建和使用此新功能的过程。
如果您在参考资料中的任何地方都看不到 ValueTuple,则需要从 NuGet 下载 System.ValueTuple 4.3.0 包。如果您使用的是 .NET 4.7 或更高版本或 .NET Standard Library 2.0 或更高版本,则您无需执行任何操作,因为这些已经可供您使用。
让我们看看如何重写GetPerson方法以使用新的语法风格。
private static (string, DateTime, int) GetPerson()
{
DateTime dateOfBirth = new DateTime(1991, 07, 27);
return ("Jonathon Pluralsight", dateOfBirth, CalculateAge(dateOfBirth));
}
我们在这里看到的第一个变化是看起来有点奇怪的返回类型。(string, DateTime, int)告诉编译器这是一个ValueTuple。 return 语句被简化,以完全删除Tuple创建。我们采用类似的方法来使用此返回类型:
(string, DateTime, int) person = GetPerson();
这就是使用ValueTuple时需要对代码进行的所有更改。人员的姓名仍为Item1,出生日期仍为Item2,年龄仍为Item3 。幸运的是,语言设计者决定,这里一个有用的增强功能是能够为这些属性使用更有意义的名称。首先,我们将对GetPerson的调用更改为:
(string name, DateTime dateOfBirth, int age) person = GetPerson();
通过此更改,我们可以将Item1等替换为:
Console.WriteLine($"{person.name} was born in {person.dateOfBirth.Year} and is {person.age} years old");
此时,我们仅将代码更改为在调用GetPerson的方法中使用name、dateOfBirth和age 。 GetPerson方法的签名没有改变;它仍然是(string, DateTime, int)。我们还应该更改方法签名。通过这样做,我们可以向使用此代码的人提示每个参数的用途。我们不再仅仅依赖于一个位置。没有什么强迫我们在调用方使用相同的参数名称,但消除理解代码的障碍是一种很好的做法。GetPerson方法现在如下所示:
private static (string name, DateTime dateOfBirth, int age) GetPerson()
{
DateTime dateOfBirth = new DateTime(1991, 07, 27);
return (name: "Jonathon Pluralsight", dateOfBirth: dateOfBirth, age: CalculateAge(dateOfBirth));
}
结论
在本指南中,我们了解了如何以各种方式创建和使用元组。我们学习了如何在单个方法中创建和使用元组。然后,我们学习了如何使用元组作为方法的返回类型,并在另一个方法中使用该元组。最后,我们了解了 ValueTuples 以及如何使用它们使代码更直观。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~