3

以下只是关于语言本身的问题,我在发布更好的代码架构方法之前开始考虑这个问题,但这让我很感兴趣。

如果我有这种结构的方法

private void Foo<T>(T bar){
    //do stuff with tuples
}

在不同的类和方法中,我有一个变量

(int first, int second) myTuple = (1,2);

在这个变量的范围内,我可以做类似的事情

var firstValue = myTuple.first;

无论如何我可以传递myTupleFoo哪个可以维护元组中元素的命名,以便我可以做类似的事情bar.firstValue

4

4 回答 4

5

通过类中的解构实现T可以使用元组访问实例字段。您需要在T类中提供解构实现,以便它可以获得元组的正确值。

您可以通过以下方式解决您的问题:

  1. 在类中提供解构实现T,假设TTestClass

    public class TestClass
    {
    
        private int _first { get; set; }
    
        private int _second { get; set; }
    
        private int _third { get; set; }
    
        public TestClass(int first, int second, int third)
        {
            _first = first;
            _second = second;
            _third = third;
        }
    
        // Implementation for tuple deconstruct
        public void Deconstruct(out int first, out int second)
        {
            first = _first;
            second = _second;
        }
    
    }
    
  2. 在您的Foo方法中,您可以通过以下方式访问:

    public class Bar
    {
        public void Foo<T>(T data) where T : TestClass
        {
    
               (int first, int second) = data;
    
               //do stuff with tuples
         }
    }
    
于 2017-10-20T14:39:25.643 回答
4

元组值名称不附加到实例,而是附加到函数的变量、参数或返回。

这是所有有效的 C# 代码:

(int a, string bx) M((int x, string y) p) => p;
// ..
(int i, string s) v1 = (j:1, k:"ome");
(int m, string n) v2 = M(v1);

对于运行时,真正重要的是元组的类型(在上面的示例中始终是ValueTuple<int, string>)。这些名称只是为代码读者提供的工具便利。

于 2017-10-21T14:56:24.197 回答
1

您不能在 Foo 方法中使用名称“first”和“second”。但您可以使用 bar.Item1 或 bar.Item2。

共鸣是“第一”和“第二”的名字并不真正存在——它只是句法上的糖。编译器在这里接受 first 和 second - 但它仍然是一个 ValueTuple

于 2017-10-20T14:12:42.320 回答
1

无论如何我可以将 myTuple 传递给 Foo,它会维护元组中元素的命名,以便我可以执行 bar.firstValue 之类的操作?

泛型方法的实现不(也不应该)取决于您作为参数传递的参数。所以T可以是任何东西。值类型或引用类型。

约束只能将泛型类型限制为更具体的类型。你怎么不能为 ValueTuple 声明约束。

如果你想实现对元组起作用的东西,那么你需要实际的元组作为参数。不是泛型类型。

于 2017-10-20T14:15:37.130 回答