tags:

views:

238

answers:

3

Hi All

I'm currently trying to write a Dump() method from LinqPad equivalent iin C# for my own amusment. I'm moving from Java to C# and this is an exercise rather than a business requirement. I've got almost everything working except for Dumping a Dictionary.

The problem is that KeyValuePair is a Value type. For most other Value types I simply call the ToString method but this is insufficient as the KeyValuePair may contain Enumerables and other objects with undesirable ToString methods. So I need to work out if it's a KeyValuePair and then cast it. In Java I could use wildcard generics for this but I don't know the equivalent in C#.

Your quest, given an object o, determine if it's a KeyValuePair and call Print on its key and value.

Print(object o) {
   ...
}

Thanks!

+2  A: 

you have the is keyword http://msdn.microsoft.com/es-es/library/scekt9xw(VS.80).aspx

Pablo Castilla
English language link is http://msdn.microsoft.com/library/scekt9xw(VS.80).aspx
Tom Cabanski
I think this gets problematic with generics. Since KeyValuePair<string, int> is not the same as KeyValuePair<int, string> .. And he actually doesn't care what type it is, as long as there is a .ToString() in it.. (T : class)
Tigraine
+6  A: 

If you don't know the types stored in the KeyValuePair you need to exercise a bit of reflection code.

Let's look at what is needed:

First, let's ensure the value isn't null:

if (value != null)
{

Then, let's ensure the value is generic:

    Type valueType = value.GetType();
    if (valueType.IsGenericType)
    {

Then, extract the generic type definition, which is KeyValuePair<,>:

        Type baseType = valueType.GetGenericTypeDefinition();
        if (baseType == typeof(KeyValuePair<,>))
        {

Then extract the types of the values in it:

            Type[] argTypes = baseType.GetGenericArguments();

Final code:

if (value != null)
{
    Type valueType = value.GetType();
    if (valueType.IsGenericType)
    {
        Type baseType = valueType.GetGenericTypeDefinition();
        if (baseType == typeof(KeyValuePair<,>))
        {
            Type[] argTypes = baseType.GetGenericArguments();
            // now process the values
        }
    }
}

If you've discovered that the object does indeed contain a KeyValuePair<TKey,TValue> you can extract the actual key and value like this:

object kvpKey = valueType.GetProperty("Key").GetValue(value, null);
object kvpValue = valueType.GetProperty("Value").GetValue(value, null);
Lasse V. Karlsen
I was just about to suggest exactly that.. :) Good answer
Tigraine
Amazing answer, thank you very much
Logan
A: 

Presuming you are using the generic KeyValuePair then you need probably want to test for a particular instantiation, such as one created using a string for both key and value:

public void Print(object o) 
{
    if (o == null)
        return;

    if (o is KeyValuePair<string, string>)
    {
        KeyValuePair<string, string> pair = (KeyValuePair<string, string>)o;
        Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
    }
}

If you want to test for any type of KeyValuePair then you'll need to use reflection. Do you?

Dan Diplo