是否有一种方法可以使用Tuple类,但在其中提供项目的名称?

例如:

public Tuple<int, int, int int> GetOrderRelatedIds()

它返回OrderGroupId、OrderTypeId、OrderSubTypeId和OrderRequirementId的id。

让我的方法的用户知道哪个是哪个就好了。(当您调用该方法时,结果为result。Item1,结果。第二条,结果。Item3 result.Item4。不清楚哪个是哪个。)

(我知道我可以创建一个类来保存所有这些id,但这些id已经有自己的类,它们生活在其中,为这个方法的返回值创建一个类似乎很愚蠢。)


当前回答

下面是你所问问题的一个过于复杂的版本:

class MyTuple : Tuple<int, int>
{
    public MyTuple(int one, int two)
        :base(one, two)
    {

    }

    public int OrderGroupId { get{ return this.Item1; } }
    public int OrderTypeId { get{ return this.Item2; } }

}

为什么不直接创建一个类呢?

其他回答

直到c# 7.0,除了定义自己的类型,还没有办法做到这一点。

您可以编写一个包含元组的类。

您需要重写Equals和GetHashCode函数

和==和!=操作符。

class Program
{
    public class MyTuple
    {
        private Tuple<int, int> t;

        public MyTuple(int a, int b)
        {
            t = new Tuple<int, int>(a, b);
        }

        public int A
        {
            get
            {
                return t.Item1;
            }
        }

        public int B
        {
            get
            {
                return t.Item2;
            }
        }

        public override bool Equals(object obj)
        {
            return t.Equals(((MyTuple)obj).t);
        }

        public override int GetHashCode()
        {
            return t.GetHashCode();
        }

        public static bool operator ==(MyTuple m1, MyTuple m2)
        {
            return m1.Equals(m2);
        }

        public static bool operator !=(MyTuple m1, MyTuple m2)
        {
            return !m1.Equals(m2);
        }
    }

    static void Main(string[] args)
    {
        var v1 = new MyTuple(1, 2);
        var v2 = new MyTuple(1, 2);

        Console.WriteLine(v1 == v2);

        Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
        d.Add(v1, 1);

        Console.WriteLine(d.ContainsKey(v2));
    }
}

将返回:

True

True

TL:DR ->系统。ValueTuples可以自定义字段System的名称。元组不能。

澄清一下,在c# 7.0及更高版本中有两种不同类型的元组。

系统。元组 而且 系统。ValueTuple

当你通过tuple <…>类:

public Tuple<int, string, int> GetUserInfo();

您正在声明一个Tuple对象数据类型。

当你通过圆括号声明一个元组时:

public (int id, string name, int age) GetUserInfo();

您正在声明ValueTuple值数据类型。

每一个都有不同的功能和行为。在你的问题中,你的方法返回一个系统。元组对象。

不幸的是,通过系统创建的元组对象。元组类没有内置功能来给每个属性一个自定义名称。它们总是默认为ItemN,这取决于它们包含多少属性。

系统。另一方面,ValueTuple值可以包含自定义命名字段。

要了解更多信息,您可以参考Tuple类型(c#参考)和/或上面每个类的链接。但从本质上讲,文档强调的两种不同类型元组的一些关键区别是:

c#元组,由System。ValueTuple类型是不同的 由System表示的元组。Tuple类型。主要的 区别如下: 系统。ValueTuple类型是值类型。系统。元组类型是引用类型。 系统。ValueTuple类型是可变的。系统。元组类型是不可变的。 系统的数据成员。ValueTuple类型是字段。系统的数据成员。元组类型是属性。

如果你的方法需要返回一个System。元组对象,或者你更想要这种类型的对象的行为,那么在写这篇文章时,你无法实现你想要的。但是,如果您的方法可以返回System。ValueTuple值,然后您可以在返回值中给它自定义命名字段。

为什么不使用多个返回而不是使用元组

var handler = GenerateFromMethod1(hits);
Process(handler.string1, handler.string1);

private static (string string1, string string2) GenerateFromMethod1()
{

}

只是补充一下@MichaelMocko的答案。元组目前有几个陷阱:

你不能在EF表达式树中使用它们

例子:

public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        // Selecting as Tuple
        .Select(person => (person.Name, person.Surname))
        .First();
}

这将导致编译失败,出现“表达式树可能不包含元组文字”错误。不幸的是,表达式树API在向语言中添加元组时并没有扩展对元组的支持。

跟踪(并投票)这个问题的更新:https://github.com/dotnet/roslyn/issues/12897

为了解决这个问题,你可以先将其转换为匿名类型,然后将值转换为元组:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => new { person.Name, person.Surname })
        .ToList()
        .Select(person => (person.Name, person.Surname))
        .First();
}

另一种选择是使用ValueTuple。创建:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname))
        .First();
}

引用:

https://www.damirscorner.com/blog/posts/20181207-NoSupportForTuplesInExpressionTrees.html 将匿名类型转换为新的c# 7元组类型

你不能用lambda解构它们

有一个增加支持的提议:https://github.com/dotnet/csharplang/issues/258

例子:

public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname));
}

// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })

// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })

引用:

c# 7元组和lambda

它们不会很好地连载

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main() {
        var me = (age: 21, favoriteFood: "Custard");
        string json = JsonConvert.SerializeObject(me);

        // Will output {"Item1":21,"Item2":"Custard"}
        Console.WriteLine(json); 
    }
}

元组字段名仅在编译时可用,并在运行时完全删除。

引用:

使值元组属性名在运行时可解析 c# 7元组支持(Newtonsoft.Json)