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)
{
}
Related
I have a string variable which holds some value and I want to be able to check if that string exists in a dictionary as a key with its variable name.
For a clearer understanding as you can see in the following code;
string searchDuration = "200";
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","200"},
{"peripheralId","123wrong"}
};
I'm able to use ContainsKey method as following;
if (response.ContainsKey("searchDuration"))
if (searchDuration == pair.Value)
isEqual = true;
But I don't(actually can't) use it this way because;
I need to pass in every string variable dynamically, I can't write every variable name as a string to pass in to ConstainsKey method
It only check values and there might be multiple values with "200", this situation gives me false results.
I want to compare the value "200" only with related key which is "searchDuration", not with "txPowerLevel" which has the same value.
Is there a way to check whether a string variable exists as a key in a dictionary to compare it's value with dictionary members?
I'd suggest this approach:
string searchDuration = "200";
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","-16"},
{"peripheralId","123wrong"}
};
var wasItThere = response.TryGetValue(nameof(searchDuration), out var value);
Console.WriteLine(wasItThere && (value == searchDuration));
TryGetValue is better than ContainsKey since it gets the value at the same time as checking whether the key is there.
nameof is used to convert the variable name to its string representation.
I have explicitly not used pair.Value since that code in your original question strongly implies you are iterating through the Dictionary. This is not a good idea (performance wise).
If the variables you want to compare are all part of an object, then you can inspect that object with reflection and compare what is found inside the object with what is present in the Dictionary. Here is how:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var obj = new { searchDuration = "200", txPowerLevel = "100", other = "123"};
var stringProperties = obj
.GetType()
.GetProperties()
.Where(pi => pi.PropertyType == typeof(string) && pi.GetGetMethod() != null)
.Select(pi => new
{
Name = pi.Name,
Value = pi.GetGetMethod().Invoke(obj, null)}
)
.ToList();
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","200"},
{"peripheralId","123wrong"}
};
foreach (var item in stringProperties)
{
string v;
response.TryGetValue(item.Name, out v);
Console.WriteLine(item.Name + ": obj value=" + item.Value + ", response value=" + (v ?? "--N/A--"));
}
}
}
Working Fiddle: https://dotnetfiddle.net/gUNbRq
If the items are present as local variables then it can probably also be done (e.g. see here), but I would recommend putting it in object to keep the values you want to inspect separate from other variables that your method needs and uses.
I'm trying to convert command line arguments to different formats. For example, if I'm trying to get a specific user, it would be GetUser=UserName, but I also have methods that don't need the equals sign, such as GetAllUsers. Right now I'm currently splitting on the = but I don't need to do that for all commands. I tried setting it to a conditional, where if = is detected, it will split, otherwise it will just take the argument as a string, but I'm getting Cannot implicitly convert type 'string' to 'System.Collections.Generic.Dictionary<string, string>
Code:
public static Dictionary<string, string> ParseArgs(string[] args)
{
Dictionary<string, string> results = new Dictionary<string, string>();
foreach (string arg in args)
{
string[] parts = arg.Split('=');
if (parts.Length > 1)
{
results[parts[0]] = parts[1];
continue;
}
else
{
results = Convert.ToString(arg);
}
}
return results;
}
You're trying to assign a string to a dictionary object. If you want a collection (like Dictionary) then you should use the Add method like so:
foreach (string arg in args)
{
string[] parts = arg.Split('=');
if (parts.Length > 1)
{
//results[parts[0]] = parts[1];
results.Add(parts[0], parts[1]);
continue;
}
else
{
results.Add("GetUser", arg);
}
}
I've forced it to be "GetUser" as the value here, but you may actually want something different. Your dictionary is using Key-Value pairs and you would say results["GetUser"] to return a string for "GetUser". You could also use TryGetValue to validate that GetUser was actually provided.
Additionally, if you just want to return the string that's after GetUser (e.g. Username), then you could change results to a string and just assign that directly and skip the whole use of a Dictionary, which seems overkill for your sample (perhaps your real project is much more complex though).
In the else part, you are trying to assign string to dictionary via the statement results = Convert.ToString(arg);
So, please change else part with something like as shown below:
public static Dictionary<string, string> ParseArgs(string[] args)
{
Dictionary<string, string> results = new Dictionary<string, string>();
foreach (string arg in args)
{
string[] parts = arg.Split('=');
if (parts.Length > 1)
{
results[parts[0]] = parts[1];
// continue; no need to use continue, as there are no more statements after this if-else, loop will anyway continue. but please uncomment if you have any in your actual code.
}
else
{
results[arg] = arg; // assuming arg string in args won't repeat, meaning its unique. Otherwise please use ContaineKey if condition before adding or over-writing.
}
}
return results;
}
I am trying to implement a dictionary in such a way that It will only add in a certain value to a key if that new value is greater than the currently existing value
So the basic scenarios would be:
If the key is not available, it will create a new key and a value
If the key if available, it will check if the current value is greater than the value that is already assigned to that key and will only update if it is greater.
Before I explain the problem I am facing here is my code
static IDictionary<string, string> versionStack = new Dictionary<string, string>();
foreach(var item in RequiredApps)
{
nameOfApp = item.Key;
minimumVersionOfApp = item.Value.minVersion;
if (versionStack.TryGetValue(nameOfApp, out minimumVersionOfApp))
{
if (Convert.ToInt32(minimumVersionOfApp) >= Convert.ToInt32(item.Value.minVersion))
minimumVersionOfApp = item.Value.minVersion;
}
versionStack[nameOfApp] = minimumVersionOfApp;
}
Note: Kindly do not worry about the for loop as it works fine and gives no problem there. Just want to display only the specific code that gives me problem
Right now I have been able to fulfill the functionality to a certain level but the problem is when the TryGetValue is executed it turns all my values to null.
I am using the TryGetValue to see if a key has a value and if so to retrieve it.
I am stuck here right now and would appreciate if anyone can help show me what I am doing wrong.
Edit :-
Given that the problem I am facing is quite unclear and as suggested by Rufus L I am adding a sample dummy application with exactly the problem I am facing
Hope this helps to clear any confusion :)
class Program
{
static IDictionary<string, string> versionStack = new Dictionary<string, string>();
static string appName;
static string minVersion;
static void Main(string[] args)
{
AddOnce();
AddTwice();
}
public static void AddOnce()
{
appName = "app01";
minVersion = "1.0";
versionStack.Add(appName, minVersion);
}
public static void AddTwice()
{
string existingValue;
appName = "app01";
minVersion = "3.0";
if (!versionStack.TryGetValue("app01", out existingValue) || Convert.ToInt32(existingValue) < Convert.ToInt32(minVersion))
{
versionStack[appName] = minVersion;
}
}
}
Based on the code you've shown, it looks like the problem is that you're using minimumVersionOfApp as the out parameter to the TryGetValue method, which will be set to null if TryGetValue fails, but then we're using it anyway.
Remember that the contract with any out parameter is that the method must assign a value to it before it returns. Typically (and specifically in this case), if TryGetValue returns false, then the out parameter is set to the default value for the type, which is null for classes.
Then, after the first if statement, you are assigning the value to the key even when TryGetValue returns false, which is likely why you're getting null values.
Instead, only use the out parameter if TryGetValue succeeds.
Here's a sample code that does this:
foreach(var item in RequiredApps)
{
var appName = item.Key;
string existingValue; // Note that this should be the same type as item.Value
// If the key doesn't exist (the first condition),
// or it does exist and our value is greater than the existing one (second condition)
// then update the key with our new value
if (!dependentModuleStack.TryGetValue(appName, out existingValue) ||
Convert.ToInt32(existingValue) < Convert.ToInt32(item.Value.minVersion))
{
versionStack[appName] = item.Value.minVersion;
}
}
It looks like your issue is not with Dictionary.TryGetValue, but Convert.ToInt32
The version number is a double, and not an integer. you should use the Convert.ToDouble instead of Convert.ToInt32
if (!versionStack.TryGetValue("app01", out existingValue) || Convert.ToDouble(existingValue) < Convert.ToDouble(minVersion))
{
versionStack[appName] = minVersion;
}
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}")
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.