我有一个用例,需要检查一个值是否是C 7值元组,如果是,则循环遍历每个项。我试着用obj is ValueTupleobj is (object, object)检查,但都返回false。我发现我可以使用obj.GetType().Name并检查它是否以"ValueTuple"开头,但这对我来说似乎很糟糕。任何其他选择都将受到欢迎。
我还有一个问题就是要买每一件东西。我试图用这里找到的解决方案获取Item1,但((dynamic)obj).GetType().GetProperty("Item1")返回空值。我希望我能做一个while来获得每一个项目。但这不管用。我怎样才能得到每一个项目?
更新-更多代码

if (item is ValueTuple) //this does not work, but I can do a GetType and check the name
{
    object tupleValue;
    int nth = 1;
    while ((tupleValue = ((dynamic)item).GetType().GetProperty($"Item{nth}")) != null && //this does not work
        nth <= 8)
    {
        nth++;
        //Do stuff
    }
}

最佳答案

结构在c_中不继承,因此ValueTuple<T1>ValueTuple<T1,T2>ValueTuple<T1,T2,T3>等是不同的类型,它们不从ValueTuple继承为基。因此,obj is ValueTuple检查失败。
如果您正在寻找具有任意类型参数的ValueTuple,您可以检查该类是否为“cc>”:

private static readonly Set<Type> ValTupleTypes = new HashSet<Type>(
    new Type[] { typeof(ValueTuple<>), typeof(ValueTuple<,>),
                 typeof(ValueTuple<,,>), typeof(ValueTuple<,,,>),
                 typeof(ValueTuple<,,,,>), typeof(ValueTuple<,,,,,>),
                 typeof(ValueTuple<,,,,,,>), typeof(ValueTuple<,,,,,,,>)
    }
);
static bool IsValueTuple2(object obj) {
    var type = obj.GetType();
    return type.IsGenericType
        && ValTupleTypes.Contains(type.GetGenericTypeDefinition());
}

要根据类型获取子项,可以使用不是特别快的方法,但应该做到以下几点:
static readonly IDictionary<Type,Func<object,object[]>> GetItems = new Dictonary<Type,Func<object,object[]>> {
    [typeof(ValueTuple<>)] = o => new object[] {((dynamic)o).Item1}
,   [typeof(ValueTuple<,>)] = o => new object[] {((dynamic)o).Item1, ((dynamic)o).Item2}
,   [typeof(ValueTuple<,,>)] = o => new object[] {((dynamic)o).Item1, ((dynamic)o).Item2, ((dynamic)o).Item3}
,   ...
};

这样你就可以做到:
object[] items = null;
var type = obj.GetType();
if (type.IsGeneric && GetItems.TryGetValue(type.GetGenericTypeDefinition(), out var itemGetter)) {
    items = itemGetter(obj);
}

10-02 01:26