Say I have a method like this:
public void Foo(object arguments)
and say I need to detect if the type of arguments
is actually an enumeration. I would write something like this:
if (arguments is IEnumerable)
Now, let's say I need to detect if it's an enumeration of KeyValuePair (regardless of the type of the key and the type of the value). My instinct would be to write something like this:
if (arguments is IEnumerable<KeyValuePair<,>>)
but visual studio complains that Using the generic type 'KeyValuePair<TKey, TValue>' requires 2 type arguments
.
I also tried:
if (arguments is IEnumerable<KeyValuePair<object, object>>)
but it returns false if the key is anything but an object (such as a string
for example) or if the value is anything but an object (such as an int
for example).
Does anybody have suggestions how I could determine if an enumeration contains KeyValuePairs regardless of the key type and the value type and if so, how can I loop through these pairs?
A key-value pair consists of two related data elements: A key, which is a constant that defines the data set (e.g., gender, color, price), and a value, which is a variable that belongs to the set (e.g., male/female, green, 100). Fully formed, a key-value pair could look like these: gender = male. color = green.
KeyValuePair<TKey,TValue> is used in place of DictionaryEntry because it is generified. The advantage of using a KeyValuePair<TKey,TValue> is that we can give the compiler more information about what is in our dictionary. To expand on Chris' example (in which we have two dictionaries containing <string, int> pairs).
In C# programming, we have different methods to iterate over the dictionary. The foreach loop method is also used for iterating over the dictionary. This article will discuss how to iterate over a dictionary using a foreach loop.
A key-value pair (KVP) is a set of two linked data items: a key, which is a unique identifier for some item of data, and the value, which is either the data that is identified or a pointer to the location of that data. Key-value pairs are frequently used in lookup tables, hash tables and configuration files.
You need some reflection here:
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;
}
}
In order to rebuild an Enumerable
and iterate over it, you could use the following approach that uses dynamic
:
List<KeyValuePair<Object, Object>> list = new List<KeyValuePair<Object, Object>>();
foreach (dynamic kvp in (IEnumerable)arguments)
list.Add(new KeyValuePair<Object, Object>(kvp.Key, kvp.Value));
or, with LINQ
:
List<KeyValuePair<Object, Object>> list = (from dynamic kvp in (IEnumerable)arguments select new KeyValuePair<Object, Object>(kvp.Key, kvp.Value)).ToList();
I also found another solution, but this is pure madness:
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));
}
}
}
References:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With