在C#中通过索引获取元组值

4

我有一个问题,我有一个简单的命名元组和一个包含8个元组值的配置,我需要按照索引在这8种情况中使用它们,所以它看起来像这样:

    private int[] delayParametersIndexSetup = new int[] {1, 0, 0, 1, 1, 0, 0, 1 };
    private (int delayWheel, int delayDiag) delayParameters = (1, 500);

换句话说,当我迭代delayParametersIndexSetup时,我希望获取该索引表示的元组值,例如:
   foreach (var index in delayParametersIndexSetup)
   {
       var value = this.delayParameters.ToTuple()[index];
   }

我知道我可以使用Item1,Item2等等,但是我希望这个方法更加灵活,而不用使用case语句。

我看到可以使用ITuple(在文档中称为item[x]属性),但是我的VS中找不到这种类型。

这种方式可行吗?


我可能有点困惑,但是你为什么要尝试使用元组作为集合呢?元组不是键/值存储器吗?就像字典一样。 - Mark Davies
@MarkDavies 不,一个元组不是键/值存储。元组的Item1并不比Item2更重要。OP想根据外部数据动态返回元组中的 Item1Item2 - GSerg
如果您不想使用case语句,最好的选择是尝试使用反射来调用ItemX成员。 - Dbuggy
3个回答

5

ValueTuple 实现了 ITuple 接口,因此您可以执行以下操作:

int value = (int)((ITuple)this.delayParameters)[index];

然而,这将产生两次装箱(boxing)操作:首先整个元组作为一个整体被装箱(因为它被强制转换为ITuple),然后特定的元组成员也被装箱。因此,这可能是一个坏主意

你最好用数组替换元组,或者使用像这样的自定义对象:

public struct DelayParameters
{
    public int DelayWheel { get; }
    public int DelayDiag { get; }

    public int this[int index] => index switch
    {
        0 => DelayWheel,
        1 => DelayDiag,
        _ => throw new IndexOutOfRangeException(nameof(index)),
    };

    public DelayParameters(int delayWheel, int delayDiag) => 
        (DelayWheel, DelayDiag) = (delayWheel, delayDiag);
}

1
它明确实现了ITuple接口,这意味着您需要首先转换为ITuple。
private int[] delayParametersIndexSetup = new int[] { 1, 0, 0, 1, 1, 0, 0, 1 };
private (int delayWheel, int delayDiag) delayParameters = (1, 500);

public void Go()
{
    foreach (var index in delayParametersIndexSetup)
    {
        ITuple value = delayParameters;
        var v = value[index];
        Console.WriteLine(v);
    }
}

0

元组似乎不适合这个任务的类型,至少在我理解的范围内。

以下是其他一些想法。

A. 字典

您可以使用字典来完成此任务。

private int[] delayParametersIndexSetup = new int[] {1, 0, 0, 1, 1, 0, 0, 1 };
private Dictionary<int, int> delayParameters = new Dictionary<int, int>()
{
    { 0, 1 },
    { 1, 500 }
};

(...)

foreach (var index in delayParametersIndexSetup)
{
    var value = this.delayParameters[index];
}

您可以使用以下方法同时存储数值和名称:
private Dictionary<int, (string Name, int Delay)> delayParameters = new Dictionary<int, (string Name, int Delay)>()
{
    { 0, ("Wheel", 1) },
    { 1, ("Diag", 500) }
};

B. 数组 - 连续的

如果值是连续的,列表或数组也可以使用。

private int[] delayParametersIndexSetup = new int[] {1, 0, 0, 1, 1, 0, 0, 1 };
private int[] delayParameters = new int[]{1,500};

(...)
foreach (var index in delayParametersIndexSetup)
{
   var value = delayParameters[index];
}

C. 数组/列表 + Linq

您还可以将索引、名称和值存储在数组或列表中。

var delayParametersIndexSetup = new int[] { 1, 0, 0, 1, 1, 0, 0, 1 };
var delayParameters = new List<(int Index, string Name, int Delay)>() {
    (0, "Wheel", 1),
    (1, "Diag", 500)
};
foreach (var index in delayParametersIndexSetup)
{
    var p = delayParameters.First(p => p.Index == index);
    Console.WriteLine($"{p.Name}:{p.Delay}");
}

Diag:500
Wheel:1
Wheel:1
Diag:500
Diag:500
Wheel:1
Wheel:1
Diag:500

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接