I have a function that gets two strings - a key and a value.
I need to parse the value from string to enum.
the key represent which enum I need to use.
I wanted to use "if"s -
if (keyString == "e1")
{
(MyEnum1)Enum.Parse(typeof(MyEnum1), valueString, true);
}
else if (keyString == "e2")
{
(MyEnum2)Enum.Parse(typeof(MyEnum2), valueString, true);
}
else if .....
But then I thought maybe I can create a dictionary of key and enum -
<"e1", MyEnum1>,
<"e2", MyEnum2>,
...
and then use the dictionary's values for the enum parsing
(dic[keyString])Enum.Parse(typeof(dic[keyString]), valueString, true)
but I couldn't do it..
I there any other way?
Just store the type directly in the dictionary (i.e. store the result of typeof(MyEnum1)):
Dictionary<string, Type> KeyToEnum = new Dictionary<string, Type>();
KeyToEnum["e1"] = typeof(MyEnum1);
KeyToEnum["e2"] = typeof(MyEnum2);
Object EnumValue = Enum.Parse(dic[keyString), valueString, true);
// Note that EnumValue is an object, because we can't know at compile time what the type will be.
Note that if instead of "e1", "e2"... you actually had "MyEnum1", "MyEnum2" (i.e. the actual name of the type you could do Type.GetType(MyKey) instead of the dictionary.
Related
I want to use the value of a dictionary without assigning it to a variable:
Dictionary<int, string> LayoutByID = new Dictionary<int, string>() {
{ 0, "foo"},
{ 1, "bar"}
// ...
};
I can for e.g. print the values if I create a variable:
string b;
LayoutByID.TryGetValue(1,out b);
print("Trying Dictionary to retrieve value for 1: " + b);
But I was wondering if there is a simpler way, something like:
print("Trying Dictionary to retrieve value for 1: " + LayoutByID.TryGetValue(1 [???]));
I understand I could write a function with a switch in it that would work similarly, but using Dictionaries might be cheaper as I have a longer list.
Thanks for advice!
You can access the Dictionary with the key like var x = LayoutByID[0]; But you will get an exception, if the Dictionarydoes not contain an entry with that key.
In order to avoid an exception being throw, you can first check if the key exists using LayoutByID.ContainsKey() - and then write your logic for those cases:
if (LayoutByID.ContainsKey(0)) // Check if the key exists (replace 0 with whatever)
{
var x = LayoutByID[0]; // Access the value and do whatever with it
// ...
}
else
{
// Key doesn't exist:
// Do something else
}
or with C# 6.0 you could also print like this
var key = -1;
var myString = string.Empty;
LayoutByID.TryGetValue(key, out myString);
Console.WriteLine($"Trying Dictionary to retrieve value for {key}: {myString ?? "Error: Invalid ID"}");
You can create your own extension method.
[Extension]
public static string GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue>,
TKey key,
TValue defaultValue)
{
if(this.ContainKey(key) == true) return this[i];
return defaultValue;
}
Then use it
Console.WriteLine("Print value for key 1: " + LayoutByID.GetValueOrDefault(1, ""));)
With extension method you will get more clearer and readable code and can use same logic in other places
int selectingvalue = 1;
print(LayoutByID.ContainsKey(selectingvalue) ? LayoutByID.First(x => x.Key == selectingvalue).Value : "");
The problem you seem to have with not wanting to assign to a variable seems to be that you want to retrieve a Dictionary value in short and concise code without the extra 'noise' of having to check the value exists and prevent an "unhandled null exception".
In this case I would recommend using a null-coalescing operator. It works like this:
x ?? y
If x is null, y will be used. If x is not null, x will be used.
Console.WriteLine($"Trying Dictionary to retrieve value for 1: {LayoutByID[0] ?? "value not found"}")
This way you do not have to do any checks first, and in case of null, you will be defaulted to "value not found".
That said, its probably not the best thing to put a bit of logic inside the Console.WriteLine(). I personally would prefer to do this (although you have said you don't want to assign to a variable first):
var x = LayoutByID[0] ?? "value not found"
Console.WriteLine($"Trying Dictionary to retrieve value for 1: {x}")
In my desktop C# application I start with a dictionary. I want to be able to check this dictionary for a key. If the dictionary has this key, I would like to pass it on to a method. If the dictionary doesn't have this key, I would like to create a blank list and just pass that on instead. How can I do this?
I get the error "given key was not present in the dictionary". Can I add a default so it is never null maybe?
// myDic was declared as a Dictionary<string, List<string>
// Here is how I call someFunction
string text = SomeFunction(stringValue1, stringValue2, myDic[field1.field2]);
// SomeFunction looks like this
string SomeFunction (string string1, string string2, List<string> ra)
{
// method
return stringResult;
}
Updated based on comments. To pass one key that may or may not exist you may do this(assuming the value is a List):
// assuming the method we are calling is defined like this:
// public String SomeFunction(string string1, String string2, List<String> ra)
List<string> valueToPassOn;
if (_ra.ContainsKey(lc.Lc))
{
valueToPassOn = _ra[lc.Lc]
}
else
{
valueToPassOn = new List<string>();
}
string text = tooltip.SomeFunction(something1, something2, valueToPassOn);
Should you want to pass an entire dictionary (as the question originally read), regardless of whether or not the dictionary exists:
You have two options. Either create the dictionary regardless like this:
if (myDic == null)
{
// change var and var2 to the types of variable they should be, ex:
myDic = new Dictionary<string, List<string>>();
}
string text = SomeFunction(stringValue1, stringValue2, myDic);
or, what is probably the better option, in the declaration of the function SomeFunction add a dictionary as a variable with a default parameter. Just be sure that your function knows what to do if the dictionary is null.
string SomeFunction(string string1, string string2, Dictionary dictionary = null)
{
// method here
}
You can check if the key exists using ContainsKey method and if it returns false you can pass a default value you want:
// replace default(string) with the value you want to pass
// if the key doesn't exist
var value = myDic.ContainsKey(field1.field2) ? myDic[field1.field2] : default(string);
string text = SomeFunction(stringValue1, stringValue2, value);
What you need to do is make sure the dictionary actually contains the given key in the dictionary.
If you need to extract the value by key, use TryGetValue method:
string value;
if (myDict.TryGetValue(key, out value))
{
// Key exists in the dictionary, do something with value.
}
Use one of the following snippets in order to check if dictionary is empty and take some action:
var x = new Dictionary<string, string>();
if (x.Any())
{
//....
}
if (x.ContainsKey("my key"))
{
}
if (x.ContainsValue("my value"))
{
}
if (x.Count > 0)
{
}
I have this type of Dictionary:
Dictionary<string, object> dict
And one of the values is long and this is how i try to get it from the Dictionary:
long wantedid = (long)dict["wantedid"];
And this is the Exception i get:
Specified cast is not valid.
The value you are trying to read is obviously not a long value. Since you defined the Dictionary as Dictionary<string, object>, you may have put objects of any type in it.
Debug the code, and inspect the value of your required element. You can see the data type in the Watch window.
To check the type on runtime, you can try:
object o = dict["wantedid"];
if (o is long)
{
long wantedid = (long)o;
// ...
}
However, if you need to only store long values, define the dictionary as Dictionary<string, long>.
You have defined the value pair as object as it may also contain string value or anything else.
So assume if it contains "Hello" then the cast would obviously false.
You could use TryParse to make sure the value is a long. It could be something like this:
long wantedid;
bool isLong = long.TryParse(dict["wantedid"].ToString(), out wantedid);
if (isLong)
{
//do whatever you want to because you know the object can be a long
}
I'm looking way to Create KeyValuePair instance and setting key & Value dynamically using reflection.
This is part of
foreach(var prop in this.GetType().GetProperties())
loop which iterates through properties and tries to recover them according to some conditions. KeyValue Pair is seems to be complicated.
I have these two type definitions
var keyType = prop.PropertyType.GetGenericArguments()[0];
var valueType = prop.PropertyType.GetGenericArguments()[1];
Here I can create an Instance of my KeyValuePair..
var keyValuePair = Activator.CreateInstance(prop.PropertyType);
But the key and the value are read only properties from outside and could be set only by constructor.
Any Ideas ??
Call the constructor with the values for Key and Value:
var keyValuePair = Activator.CreateInstance(prop.PropertyType, new [] {key, val});
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!
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);
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?
you have the is keyword
http://msdn.microsoft.com/es-es/library/scekt9xw(VS.80).aspx