如何遍历元组项
how to iterate over tuple items
当我在编译时不知道元组由哪些类型组成时,如何迭代元组中的项目?我只需要一个 IEnumerable 对象(用于序列化)。
private static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>))
{
var x = tuple as Tuple<object, object>;
yield return x.Item1;
yield return x.Item2;
}
}
这里的一个问题是您必须处理多个 Tuple
类型:Tuple<T1, T2>
、Tuple<T1, T2, T3>
等(我假设您希望它与元组一起使用任意数量的项目。)
这是一种有点古怪的方法,它可以查看类型名称是否以 System.Tuple
:
开头
public static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition().FullName.StartsWith("System.Tuple"))
{
for (int i = 1;; ++i)
{
var prop = t.GetProperty("Item" + i);
if (prop == null)
yield break;
yield return prop.GetValue(tuple);
}
}
}
如果你不喜欢 FullName.StartsWith(...)
的笨拙,你可以像这样让它更安全:
public static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (isTupleType(t))
{
for (int i = 1;; ++i)
{
var prop = t.GetProperty("Item" + i);
if (prop == null)
yield break;
yield return prop.GetValue(tuple);
}
}
}
private static bool isTupleType(Type type)
{
if (!type.IsGenericType)
return false;
var def = type.GetGenericTypeDefinition();
for (int i = 2;; ++i)
{
var tupleType = Type.GetType("System.Tuple`" + i);
if (tupleType == null)
return false;
if (def == tupleType)
return true;
}
}
您的代码没有按预期工作,因为当您用作元组时,您期望 Tuple<object,object>
完全匹配,但事实并非如此
您可以尝试以下更通用的方法(如果您总是希望有两个项目)
class Program
{
static void Main(string[] args)
{
Tuple<string, string> tuples = new Tuple<string, string>("test","test");
foreach (string item in TupleToEnumerable<string>(tuples))
{
Console.WriteLine(item);
}
}
private static IEnumerable<T> TupleToEnumerable<T>(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>))
{
var x = tuple as Tuple<T, T>;
yield return x.Item1;
yield return x.Item2;
}
}
}
您可以使用 Type.GetProperties
通过反射访问属性及其值
var values = tuple.GetType().GetProperties().Select(p => p.GetValue(tuple));
所以你的方法将是非常简单的Linq查询
private static IEnumerable TupleToEnumerable(object tuple)
{
// You can check if type of tuple is actually Tuple
return tuple.GetType()
.GetProperties()
.Select(property => property.GetValue(tuple));
}
在.NET Core 2.0+或.NET Framework 4.7.1+中,有
- t.Length
- t[i]
来自界面ITuple interface
var data = (123, "abc", 0.983, DateTime.Now);
ITuple iT = data as ITuple;
for(int i=0; i<iT.Length;i++)
Console.WriteLine(iT[i]);
当我在编译时不知道元组由哪些类型组成时,如何迭代元组中的项目?我只需要一个 IEnumerable 对象(用于序列化)。
private static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>))
{
var x = tuple as Tuple<object, object>;
yield return x.Item1;
yield return x.Item2;
}
}
这里的一个问题是您必须处理多个 Tuple
类型:Tuple<T1, T2>
、Tuple<T1, T2, T3>
等(我假设您希望它与元组一起使用任意数量的项目。)
这是一种有点古怪的方法,它可以查看类型名称是否以 System.Tuple
:
public static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition().FullName.StartsWith("System.Tuple"))
{
for (int i = 1;; ++i)
{
var prop = t.GetProperty("Item" + i);
if (prop == null)
yield break;
yield return prop.GetValue(tuple);
}
}
}
如果你不喜欢 FullName.StartsWith(...)
的笨拙,你可以像这样让它更安全:
public static IEnumerable TupleToEnumerable(object tuple)
{
Type t = tuple.GetType();
if (isTupleType(t))
{
for (int i = 1;; ++i)
{
var prop = t.GetProperty("Item" + i);
if (prop == null)
yield break;
yield return prop.GetValue(tuple);
}
}
}
private static bool isTupleType(Type type)
{
if (!type.IsGenericType)
return false;
var def = type.GetGenericTypeDefinition();
for (int i = 2;; ++i)
{
var tupleType = Type.GetType("System.Tuple`" + i);
if (tupleType == null)
return false;
if (def == tupleType)
return true;
}
}
您的代码没有按预期工作,因为当您用作元组时,您期望 Tuple<object,object>
完全匹配,但事实并非如此
您可以尝试以下更通用的方法(如果您总是希望有两个项目)
class Program
{
static void Main(string[] args)
{
Tuple<string, string> tuples = new Tuple<string, string>("test","test");
foreach (string item in TupleToEnumerable<string>(tuples))
{
Console.WriteLine(item);
}
}
private static IEnumerable<T> TupleToEnumerable<T>(object tuple)
{
Type t = tuple.GetType();
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Tuple<,>))
{
var x = tuple as Tuple<T, T>;
yield return x.Item1;
yield return x.Item2;
}
}
}
您可以使用 Type.GetProperties
var values = tuple.GetType().GetProperties().Select(p => p.GetValue(tuple));
所以你的方法将是非常简单的Linq查询
private static IEnumerable TupleToEnumerable(object tuple)
{
// You can check if type of tuple is actually Tuple
return tuple.GetType()
.GetProperties()
.Select(property => property.GetValue(tuple));
}
在.NET Core 2.0+或.NET Framework 4.7.1+中,有
- t.Length
- t[i]
来自界面ITuple interface
var data = (123, "abc", 0.983, DateTime.Now);
ITuple iT = data as ITuple;
for(int i=0; i<iT.Length;i++)
Console.WriteLine(iT[i]);