当其中一个部分的类型未知时,从元组中获取项目

Get Items out of a tuple when the type of one of the parts is unknown

我正在尝试获取一个可以分为两部分的动态对象 Tuple 并从中获取值。通常,这很容易,但在这种情况下,Tuple 的第二部分可以是任何内容。 (实际上它可以是任何东西。)

这是我在 LinqPad 中尝试做的测试。

// This could be a Tuple<String, String>, Tuple<String, MyCustomClass>
// The second part of the tuple could be anything.
dynamic variable = new Tuple<String, int>("Test", 123); 

if (variable is Tuple<string, dynamic> tupleVar)
{
    Console.WriteLine($"{tupleVar.Item1}, {tupleVar.Item2.ToString()}");
}

我希望 is Tuple<string, dynamic> 中的动态允许它匹配第二个值的任何内容。但它将动态视为一种类型,并且仅当创建的类型也是动态时才会匹配(或强制转换)。

有没有办法知道我的动态对象是两部分Tuple

怎么样:

is ITuple tuple when tuple.Length == 2
   && tuple[0] is string

并获取:

dynamic val = tuple[1];

有一个问题:如果 stringnull,它将不起作用。

我应该继续挖掘更长时间。看起来这会起作用:

dynamic variable = new Tuple<String, int>("Test", 123); 

if (variable?.GetType()?.Name=="Tuple`2")
{
    Console.WriteLine($"{variable?.Item1}, {variable?.Item2?.ToString()}");
}

您可以使用 pattern matching. It works even with Tuple<,> class, not only with the new ValueTuples 进行测试:

dynamic variable = new Tuple<String, int>("Test", 123);

if (variable is (string name, var value)) {
    Console.WriteLine($"{name}, {value}");
}

其中 value 隐式键入为 object?(请参阅:Nullable reference types)。

这可能是由于某些编译器魔法。有一个 System.TupleExtensions Class 声明解构函数和转换扩展方法;然而,当我们的代码中没有 using System; 时,上面的模式匹配表达式也有效。但是文档说(见上面的link):

Although these methods can be called directly, they are primarily intended for use by the C# compiler in creating and deconstructing tuples.

注:这里用dynamic貌似没什么优势。如果您不打算在编译时调用未知类型的成员,只需使用 object.