3.2.2 在 C# 中实现元组类型

3.2.2 在 C# 中实现元组类型

 

    System 命名空间中可用的实际 Tuple<T1, T2> 类型更复杂,但是,我们可以很容易实现在这一章中的我们所需要的功能。我们会按照与 .NET 类型相同的命名规则,因此,如果你不使用 .NET 4.0,就可以使用我们在所有的示例中所实现的的。完整的代码展示在清单 3.7 中。


Listing 3.7 Implementing the tuple type (C#)


public sealed class Tuple<T1, T2> {
    private readonly T1 item1;
    private readonly T2 item2;
    public T1 Item1 { get { return item1; } }
    public T2 Item2 { get { return item2; } }
    public Tuple(T1 item1, T2 item2) {
        this.item1 = item1;
        this.item2 = item2;
    }
}

    最值得注意的是该类型是不可变的。我们已经在第 1 章看到过,如何在 C# 中创建不查变类。简单地说,用 readonly 限定符标记类型的所有字段,并只提供 getter 的属性。 有趣的是,这与 F# 有点相反,F# 必须显式标记可变值。只读字段只能从构造函数的代码中进行设置,这意味着,一旦创建了该元组,其内部状态不能改变,但只有存储在元组中的两个值也是不可变的情况下。


更好的 C# 元组类型推断

 

    在继续之前,我们想向你展示了一个 C# 的技巧,使我们进一步的使用元组的示例更简明。在前面的示例中,我们必须创建元组类型的实例,用构造函数调用,要求显式声明类型参数值 。我们用新的 C# 3.0 的 var 关键字,所以,C# 编译器为我们推断出变量的类型,但是,我们还可以做得更好。

    C# 中还有一个地方支持类型推断:调用泛型方法。如果你正在调用一个泛型方法,它的类型参数用作方法参数的类型,那么,编译器就能够在这个方法被调用时,使用该方法参数值的编译时类型,来推断类型参数值[3]。为了阐明这一点,让我们看看清单 3.8。

 
Listing 3.8 Improved type inference for tuples (C#)


public static class Tuple {
    public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) {
        return new Tuple<T1, T2>(item1, item2);
    }
}
var prague = Tuple.Create("Prague", 1188000);
var seattle = Tuple.Create("Seattle", 582000);

    清单 3.8 实现一个静态方法 Create,有两个泛型参数,用这些类型的值创建一个元组。我们需要将此方法放在非泛型类中,否则,我们就必须显式指定这个泛型参数。幸运的是,C# 允许我们使用 Tuple 名字,因为类型可以按照类型参数的数量重载(Tuple 和 Tuple<T1, T2> 是两个不同的类型)。你可能不会感到惊讶,这个类在 System 命名空间中也是可用的,因此,如果你正在使用 .NET 4.0,不必自己实现。

    这个函方法体很简单:它唯一的目的是使能够通过调用方法,而不是调用构造函数,创建元组。它允许 C# 编译器使用类型推断。调用泛型方法的完整语法,包括类型参数值,因此,完整的语法,必须写成 Tuple.Create<string,int>(...)。在下一节中,我们将讨论编写计算元组的代码,因为,我们在 C# 中实现了元组类型,我们将从 C# 的代码开始,实现 F# 版本。
 

你可能感兴趣的:(C#,职场,F#,休闲,函数编程)