C# 如何在不知道键的类型和值的类型的情况下遍历KeyValuePair的枚举
假设我有这样一种方法:C# 如何在不知道键的类型和值的类型的情况下遍历KeyValuePair的枚举,c#,C#,假设我有这样一种方法: public void Foo(object arguments) if (arguments is IEnumerable) if (arguments is IEnumerable<KeyValuePair<,>>) 假设我需要检测参数的类型是否实际上是一个枚举。我会这样写: public void Foo(object arguments) if (arguments is IEnumerable) if (arguments is
public void Foo(object arguments)
if (arguments is IEnumerable)
if (arguments is IEnumerable<KeyValuePair<,>>)
假设我需要检测参数的类型是否实际上是一个枚举。我会这样写:
public void Foo(object arguments)
if (arguments is IEnumerable)
if (arguments is IEnumerable<KeyValuePair<,>>)
现在,假设我需要检测它是否是KeyValuePair的枚举(不管键的类型和值的类型)。我的直觉是这样写:
public void Foo(object arguments)
if (arguments is IEnumerable)
if (arguments is IEnumerable<KeyValuePair<,>>)
if(参数是IEnumerable)
但是VisualStudio抱怨说,使用泛型类型“KeyValuePair”需要两个类型参数
我还尝试:
if (arguments is IEnumerable<KeyValuePair<object, object>>)
if(参数是IEnumerable)
但如果键不是对象(例如字符串
),或者值不是对象(例如int
),则返回false
有人建议我如何确定枚举是否包含KeyValuePairs,而不考虑键类型和值类型,如果是,我如何循环这些对?您可以使用反射GetGenericTypeDefinition
var pair = new KeyValuePair<string, int>("asd", 123);
var isOf = pair.GetType().GetGenericTypeDefinition() == typeof(KeyValuePair<,>);
当前类型不是泛型类型。也就是说,IsGenericType返回
错
您可以使用Type.IsGenericType
我不确定你是否真的想在这里实现
在foreach
private bool Get<T>(IEnumerable<T> list, Type someType)
{
foreach (var item in list)
{
if (item.GetType()
.GetGenericTypeDefinition() == someType)
{
return true;
}
}
return false;
}
private List<T> Get2<T>(IEnumerable<T> list, Type someType)
{
return list.Where(
item => item.GetType()
.GetGenericTypeDefinition() == someType)
.ToList();
}}
private bool Get(IEnumerable list,键入someType)
{
foreach(列表中的变量项)
{
if(item.GetType()
.GetGenericTypeDefinition()==someType)
{
返回true;
}
}
返回false;
}
私有列表Get2(IEnumerable列表,键入someType)
{
返回列表。在哪里(
item=>item.GetType()
.GetGenericTypeDefinition()==someType)
.ToList();
}}
用法
var blah = Get2(list, typeof(KeyValuePair<,>));
var blah=Get2(列表,类型(KeyValuePair));
注意:所有这些都取决于你想做什么,很难做到
告诉我,以上两个都只是不知道答案的愚蠢例子
事先输入,可能无法满足您的需要
其他信息
您需要在此进行反思:
Boolean isKeyValuePair = false;
Type type = arguments.GetType();
if (type.IsGenericType)
{
Type[] genericTypes = type.GetGenericArguments();
if (genericTypes.Length == 1)
{
Type underlyingType = genericTypes[0];
if (underlyingType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
isKeyValuePair = true;
}
}
或者,使用LINQ
:
List<KeyValuePair<Object, Object>> list = (from dynamic kvp in (IEnumerable)arguments select new KeyValuePair<Object, Object>(kvp.Key, kvp.Value)).ToList();
List List=(从(IEnumerable)参数中的动态kvp选择新的KeyValuePair(kvp.Key,kvp.Value)).ToList();
我还找到了另一个解决方案,但这纯粹是疯狂:
Boolean isKeyValuePair = false;
Type type = arguments.GetType();
if (type.IsGenericType)
{
Type[] genericTypes = type.GetGenericArguments();
if (genericTypes.Length == 1)
{
Type underlyingType = genericTypes[0];
if (underlyingType.GetGenericTypeDefinition() == typeof (KeyValuePair<,>))
{
Type[] kvpTypes = underlyingType.GetGenericArguments();
Type kvpType = typeof(KeyValuePair<,>);
kvpType = kvpType.MakeGenericType(kvpTypes);
Type listType = typeof (List<>);
listType = listType.MakeGenericType(kvpType);
dynamic list = Activator.CreateInstance(listType);
foreach (dynamic argument in (IEnumerable)arguments)
list.Add(Activator.CreateInstance(kvpType, argument.Key, argument.Value));
}
}
}
布尔isKeyValuePair=false;
Type Type=arguments.GetType();
if(type.IsGenericType)
{
类型[]genericTypes=Type.GetGenericArguments();
if(genericTypes.Length==1)
{
类型UnderlineType=genericTypes[0];
if(underlyngType.GetGenericTypeDefinition()==typeof(KeyValuePair))
{
Type[]kvpTypes=underyingtype.GetGenericArguments();
类型kvpType=类型(KeyValuePair);
kvpType=kvpType.MakeGenericType(kvpTypes);
类型listType=typeof(列表);
listType=listType.MakeGenericType(kvpType);
动态列表=Activator.CreateInstance(listType);
foreach(IEnumerable参数中的动态参数)
添加(Activator.CreateInstance(kvpType,argument.Key,argument.Value));
}
}
}
参考资料:
感谢@tommaso belluzzo和@sarumanfor花时间帮助我解决这个问题。我最终接受了Tommaso的答案,因为我非常喜欢他使用
动态
类型枚举枚举中的项的想法
我还想贡献我的解决方案(主要基于Tommasso的建议)
///获取由字典、键值对枚举或匿名对象表示的键=>值对。
私有IEnumerable GetArguments(对象参数)
{
//空的
if(参数==null)
返回可枚举的.Empty();
//字典
if(参数是IDictionary字典)
返回字典
.Cast()
.Select(item=>newkeyvaluepair(item.Key.ToString(),item.Value));
//列举
if(参数为IEnumerable枚举)
{
#如果未满
var argumentsType=enumeration.GetType();
var itemType=ArgumentType.GetElementType();
var isGeneric=itemType.isgenericype;
var enumeratedType=isGeneric?itemType.GetGenericTypeDefinition():null;
#否则
var argumentsTypeInfo=enumeration.GetType().GetTypeInfo();
var itemTypeInfo=argumentsTypeInfo.GetElementType().GetTypeInfo();
var isGeneric=itemTypeInfo.IsGenericType;
var enumeratedType=isGeneric?itemTypeInfo.GetGenericTypeDefinition():null;
#恩迪夫
if(enumeratedType==typeof(KeyValuePair))
{
返回枚举
.Cast()
.Select(item=>newkeyvaluepair(item.Key.ToString(),item.Value));
}
其他的
{
抛出新ArgumentException(“您必须提供KeyValuePair的枚举”,nameof(arguments));
}
}
//反对
返回参数。GetType()
.GetRuntimeProperties()
.其中(p=>p.CanRead)
.Select(p=>newkeyvaluepair(p.Name,p.GetValue(arguments)));
}
以防万一这是一个XY问题(),您能告诉我们您试图解决的根本问题吗?“有人建议我如何确定枚举是否包含KeyValuePairs,而不考虑键类型和值类型吗?”--显而易见的选项是反射。但你的问题并不清楚,也没有证据表明你进行过研究或尝试过任何有成效的事情。正如您所发现的,C#不支持开放泛型类型……需要在编译时知道该类型。因此,即使您确定枚举包含KeyValuePair
实例,您会如何处理它们?请即兴表演