Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast object to KeyValuePair with "generic value"?

I have a ComboBox filled with mixed items of two different types. The types are either

KeyValuePair<Int32, FontFamily>

or

KeyValuePair<Int32, String>

Now there are occasions where I am only interested in the Key of the selected item, which is always an Int32.

What would be the easiest way to access the Key of the selcted item? I am thinking of something like

Int32 key = ((KeyValuepair<Int32, object/T/var/IdontCare>)combobox.SelectedItem).Key;

but that doesn´t work.

So all I have is

    Int32 key;
    if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, FontFamily)))
    {
        key = ((KeyValuePair<Int32, FontFamily)combobox.SelectedItem).Key;
    }
    else if(combobox.SelectedItem.GetType().Equals(typeof(KeyValuePair<Int32, String)))
    {
        key = ((KeyValuePair<Int32, String)combobox.SelectedItem).Key;
    }

which works, but I wonder if there is a more elegant way?

like image 305
tafkab76 Avatar asked Sep 25 '15 12:09

tafkab76


3 Answers

Casting to dynamic (poor man's reflection) can do the trick

var key = (int) ((dynamic) comboxbox.SelectedItem).Key);
like image 61
Richard Schneider Avatar answered Nov 12 '22 02:11

Richard Schneider


You certainly don't need to use GetType(). You could use:

int key;
var item = combobox.SelectedItem;
if (item is KeyValuePair<int, FontFamily>)
{
    key = ((KeyValuePair<int, FontFamily>) item).Key;
}
else if (item is KeyValuePair<int, string>)
{
    key = ((KeyValuePair<int, string>) item).Key;
}

I don't think there's really a better way without using reflection or dynamic typing, assuming you can't change the type of the selected items to your own equivalent to KeyValuePair with some non-generic base type or interface.

like image 3
Jon Skeet Avatar answered Nov 12 '22 02:11

Jon Skeet


I guess it's bound in WPF, in that case I would suggest to not use KeyValuePair<TKey,TValue> but instead an own VM class. E.g.

class MyComboItem
{
    private String _stringValue;
    private FontFamiliy _fontFamilyValue;

    public Int32 Key {get;set;}
    public object Value => (_fontFamilyValue!=null)?_fontFamilyValue:_stringValue;
}

or you could have an interface like

interface IMyComboItem
{
    Int32 Key {get;}
    object Value {get;}
}

and implement two VM classes that implement it storing the proper value type. With proper constructors and so on. Casting as you want achieve isn't possible with generics, and your solution case isn't elegant.

like image 3
alek kowalczyk Avatar answered Nov 12 '22 04:11

alek kowalczyk