将来的.NET版本会在C#中支持元组吗?

时间:2020-03-06 14:54:37  来源:igfitidea点击:

.Net 3.5不支持元组。太糟糕了,但是不确定将来的.net版本是否支持元组?

解决方案

#region tuples

    public class Tuple<T>
    {
        public Tuple(T first)
        {
            First = first;
        }

        public T First { get; set; }
    }

    public class Tuple<T, T2> : Tuple<T>
    {
        public Tuple(T first, T2 second)
            : base(first)
        {
            Second = second;
        }

        public T2 Second { get; set; }
    }

    public class Tuple<T, T2, T3> : Tuple<T, T2>
    {
        public Tuple(T first, T2 second, T3 third)
            : base(first, second)
        {
            Third = third;
        }

        public T3 Third { get; set; }
    }

    public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
    {
        public Tuple(T first, T2 second, T3 third, T4 fourth)
            : base(first, second, third)
        {
            Fourth = fourth;
        }

        public T4 Fourth { get; set; }
    }

    #endregion

并使声明更漂亮:

public static class Tuple
{
    //Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
    public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
    {
        return new Tuple<T1, T2>(t1, t2);
    }
    //etc...
}

如果我还记得我的计算机科学课,那么元组就是数据。

如果要分组数据,请创建包含属性的类。
如果我们需要类似KeyValuePair的东西,那就可以了。

我会感到惊讶,因为Cis是强类型语言,而元组却适合更动态类型的语言。随着时间的推移,Chas的漂移越来越动态,但这是语法上的糖,而不是底层数据类型的真正转变。

如果在一个实例中需要两个值,则KeyValuePair <>是一个不错的替代品,尽管比较笨拙。我们还可以使结构或者类做相同的事情,并且是可扩展的。

在我看来,匿名类型功能不是元组,而是非常相似的结构。某些LINQ查询的输出是匿名类型的集合,其行为类似于元组。

这是一条语句,它会动态创建一个类型化的元组:-):

var p1 = new {a = "A", b = 3};

参见:http://www.developer.com/net/csharp/article.php/3589916

C很容易通过泛型支持简单的元组(根据先前的回答),并且通过"含糊的键入"(许多可能的语言增强功能之一)来改善类型推断,它们可能非常非常强大。

对于它的价值,Fsupport本身就支持元组,并且已经玩过它,我不确定(匿名)元组会增加多少……简洁性带来的好处,代码清晰度很快就会丢失。

对于单一方法中的代码,有匿名类型。对于超出方法范围的代码,我认为我将坚持使用简单的命名类型。当然,如果将来的Cmake使这些不可变(尽管仍然易于使用)变得更容易,我会很高兴的。

在Cis中实现Tuple类或者重用Fclass的故事只有一半,它们使我们能够相对轻松地创建元组,但实际上并没有语法糖,这使得它们在F#等语言中非常好用。

例如,在F中,我们可以使用模式匹配来提取let语句中元组的两个部分,例如

let (a, b) = someTupleFunc

不幸的是,使用Cwould的Fclasses进行相同的操作却不那么优雅:

Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();

元组是一种强大的方法,可以从函数调用中返回多个值,而无需使用乱扔类来乱扔代码,也不必诉诸丑陋的ref或者out参数。但是,我认为,如果没有一些语法糖来使它们的创建和访问变得更加优雅,它们的使用就会受到限制。

为了使它们在哈希表或者字典中有用,我们可能希望为GetHashCode和Equals提供重载。

这是我的元组集,它们是由Python脚本自动生成的,所以我可能有些过头了:

链接到Subversion仓库

我们需要一个用户名/密码,他们都是客人

它们基于继承,但是" Tuple <Int32,String>"不会比较等于" Tuple <Int32,String,Boolean>",即使它们的前两个成员碰巧具有相同的值。

他们还实现了GetHashCode和ToString等,以及许多小的辅助方法。

用法示例:

Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
    Console.Out.WriteLine(t1 + " == " + t2);
else
    Console.Out.WriteLine(t1 + " != " + t2);

将输出:

10, a != 10, a, True

Lokad共享库(当然是开源)中有一个适当的(不是很快的)CTuple实现,其中包括以下必需功能:

  • 2-5个不可变的元组实现
  • 正确的DebuggerDisplayAttribute
  • 正确的哈希和相等性检查
  • 从提供的参数(泛型由编译器推断)生成元组的助手,以及用于基于集合的操作的扩展。
  • 经过生产测试。

我刚刚从MSDN杂志上阅读了这篇文章:Building Tuple

以下是摘录:

The upcoming 4.0 release of Microsoft
  .NET Framework introduces a new type
  called System.Tuple. System.Tuple is a
  fixed-size collection of
  heterogeneously typed data.
  ?
  ?

Like an array, a tuple has a fixed
  size that can't be changed once it has
  been created. Unlike an array, each
  element in a tuple may be a different
  type, and a tuple is able to guarantee
  strong typing for each element.

There is already one example of a
  tuple floating around the Microsoft
  .NET Framework, in the
  System.Collections.Generic namespace:
  KeyValuePair. While KeyValuePair can be thought of as the same
  as Tuple, since they are both
  types that hold two things,
  KeyValuePair feels different from
  Tuple because it evokes a relationship
  between the two values it stores (and
  with good reason, as it supports the
  Dictionary class). 
  
  Furthermore, tuples can be arbitrarily
  sized, whereas KeyValuePair holds only
  two things: a key and a value.

虽然某些语言(例如Fhave具有针对元组的特殊语法),但是我们可以从任何语言中使用新的通用元组类型。回顾第一个示例,我们可以看到,虽然元组很有用,但在没有元组语法的语言中,元组可能过于冗长:

class Program {
    static void Main(string[] args) {
        Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
        PrintStringAndInt(t.Item1, t.Item2);
    }
    static void PrintStringAndInt(string s, int i) {
        Console.WriteLine("{0} {1}", s, i);
    }
}

使用C3.0中的var关键字,我们可以删除元组变量上的类型签名,从而使代码更具可读性。

var t = new Tuple<string, int>("Hello", 4);

我们还向静态Tuple类添加了一些工厂方法,这使使用支持类型推断的语言(如C#)构建元组变得更加容易。

var t = Tuple.Create("Hello", 4);

我的开源.NET Sasa库已有元组很多年了(还有很多其他功能,例如完整的MIME解析)。我已经在生产代码中使用了好几年了。