Let's say I have a method as follows:
internal MyClass GetValue(long key)
{
if (_myDictionary.ContainsKey(key))
return _myDictionary[key];
return null; // Not found
}
IDictionary<long,MyClass> _myDictionary=...
But the above code has two lookups in the dictionary:
The test for the existance of the key
The actual retrieval of the value
Is there a more optimal way to phrase such a function, so that only one lookup is performed, but the case of "not found" is still handled via a null return (i.e., not via a not found exception)?
For example, it would have been nice if the lookup for the key returned some sort of iterator that could be used to retrieve the value or an invalid iterator if the value was not found as is done in C++. Perhaps C# has a better way of doing this given its language features.
The TryGetValue method was designed for precisely this scenario - to avoid the two lookup operations.
This method combines the functionality of the ContainsKey method and
the Item property.
If the key is not found, then the value parameter gets the appropriate
default value for the value type TValue.
[...] Use the TryGetValue method if your code frequently attempts to access
keys that are not in the dictionary. Using this method is more
efficient than catching the KeyNotFoundException thrown by the Item
property.
internal MyClass GetValue(long key)
{
MyClass maybeValue;
// Normally, one would inspect the return value of this method
// but in this case, it's not necessary since a failed lookup
// will set the out argument to default(valType), which is null
// for a reference type - exactly what you want.
_myDictionary.TryGetValue(key, out maybeValue);
return maybeValue;
}
typing up SPFiredrakes idea ...
public static class Extensions
{
public static TValue GetValueOrDefault<TKey, TValue>(
this IDictionary<Tkey, TValue> iDictionary, Tkey key)
{
TValue result;
return iDictionary.TryGetValue(key, out result) ? result : default(TValue)
}
}
used like this
var d = new Dictionary<long, SomeType>
{{1, new SomeType()}, {42, new SomeType()}, ...}
var value1 = d.GetValueOrDefault(1);
var value42 = d.GetValueOrDefault(42);
var valueX = d.GetValueOrDefault(10);
Of course, you should now check to see if your values are null, which may be why the .Net team omitted this feature.
You should use TryGetValue instead - it uses a single lookup.
internal MyClass GetValue(long key) {
MyClass res = null;
_myDictionary.TryGetValue(key, out res)
return res;
}
The call is short enough to use "inline", without adding a wrapper function. TryGetValue returns a bool indicating if the lookup has been successful or not.
Related
I have a dictionary where the key is a string and the value is an Action. I setup mapping of string keys to functions. I then have a list that I call .ForEach() on and inside this I use a value in the list as the key and then call the function associated with it. The issue will come if the key doesn't exist. How can I check this in the .ForEach function? I'd like to use the ternary operator but it doesn't seem to work.
private Dictionary<string, Func<IniConfig, object>> typeMapping = new Dictionary<string, Func<IniConfig, object>>();
typeMapping["MB"] = ProcessMB;
public object ProcessMB(IniConfig file)
{
return null;
}
object iif(bool expression, object truePart, object falsePart)
{ return expression ? truePart : falsePart; }
FilesToProcess.ForEach(x => iif(typeMapping.ContainsKey(x.ExtractType), typeMapping[x.ExtractType](x), Error(x)));
This highlights the 2nd parameter in the iif() call with error: Argument 2: cannot convert from 'void' to 'object', and the same thing for the Error(x) part.
So it seems like the ternary operator returns an object? So if I change my Action to a Func and have the return type be object and make my functions return object it compiles, but when I run a test with an invalid key it doesn't go into my Error() function it throws "The given key was not present in the dictionary" exception. I would expect it to do the ternary operation and see that typeMapping doesn't have the key and so fail to the Error() function. What am I missing?
Your iif() method is counter-intuitive here, and it seems like an over-use of LINQ. Here is what I would do:
foreach (var file in filesToProcess)
{
Func<IniConfig, object> action;
if (typeMapping.TryGetValue(file.ExtractType, out action))
{
action(file);
}
else
{
Error(file);
}
}
Makes your code easier to read too :)
Edit:
I Have found a generic way to do what you want. First you need to create an extension method for IDictionary<TKey,TVal> that simply returns the default value if a key does not exist:
public static TVal GetValueOrDefault<TKey, TVal>(this IDictionary<TKey, TVal> self, TKey key)
{
TVal ret;
self.TryGetValue(key, out ret);
return ret;
}
Then you can use the null coalescing (??) operator:
FilesToProcess.ForEach((typeMapping.GetValueOrDefault(x.ExtractType) ?? Error)(x));
Make your life easy and just create a little helper function that does what you want:
private void InvokeProcessor(IniConfig iniConfig)
{
Func<IniConfig, object> processor;
if (typeMapping.TryGetValue(x.ExtractType, out processor)
processor(iniConfig);
else
Error(iniConfig);
}
Then use it like so:
FilesToProcess.ForEach(InvokeProcessor);
Easy to read and understand. Also faster because the dictionary will only be searched once for each file.
Edit
Alright, if you really wanna use that weird iif() thing, here's how to fix it:
object iif(bool expression, Func<object> truePart, Func<object> falsePart)
{ return expression ? truePart() : falsePart(); }
...and how to use it:
FilesToProcess.ForEach(x => iif(
typeMapping.ContainsKey(x.ExtractType),
() => typeMapping[x.ExtractType](x),
() => Error(x)));
Basically the evaluation of the 2nd and 3rd argument of iif() is delayed until one of them is actually needed. In your previous version all arguments were evaluated before the execution of iff() resulting in a call to the dictionary indexer and to Error() every time a IniConfig object was processed.
A word of warning though: if you use this in production then harakiri might be your only way out of the devastating shame that will overcome you a couple years later.
I am getting a
'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll
when i run my code, everthing seems to be fine, i have been unable to find the bug. Here is path of my class caling my get/set
foreach (Tran transaction in transactions)
{
Account sAcc = items[transaction.ID1];//getting error here
Account dAcc = items[transaction.ID2];
decimal tempResult = sAcc.Money - transaction.Amount;
foreach (char s in sAcc.BorP)
Console.WriteLine(s);
And here is my get/set class
public class Tran
{
public int ID1 { get; set; }
public int ID2 { get; set; }
public decimal Amount { get; set; }
}
It was running before and i ran some more test and i keep getting this error and dont know what could be causing int. Thanks for you help
You can use the TryGetValue method of the dictionary.
Here is a sample code of using
object result; // Un-Initialized instance result
myCollection.TryGetValue("Test", out result); // If the key exists the method will out the value
Grabbed from another SO post.
From MSDN's entry on Dictionary.TryGetValue Method:
This method combines the functionality of the ContainsKey method and
the Item property.
If the key is not found, then the value parameter gets the appropriate
default value for the value type TValue; for example, 0 (zero) for
integer types, false for Boolean types, and null for reference types.
Use the TryGetValue method if your code frequently attempts to access
keys that are not in the dictionary. Using this method is more
efficient than catching the KeyNotFoundException thrown by the Item
property.
This method approaches an O(1) operation.
Also reference in this post to lookup the performance of Indexer vs TryGetValue
What is more efficient: Dictionary TryGetValue or ContainsKey+Item?
The issue you are having is that the items you are trying to read from the items array don't exist.
Use either
if (items.ContainsKey(transaction.ID1) && items.ContainsKey(transaction.ID2))
{
// Your code.
} else {
// Signal an error.
}
Or if you have a default account class that you want to use when the transactions do not exist you could use something like this.
if (!items.TryGetValue(transaction.ID1, out sAcc))
items.Add(transaction.ID1, sAcc = new Account);
if (!items.TryGetValue(transaction.ID2, out dAcc))
items.Add(transaction.ID2, dAcc = new Account);
// Your code.
Otherwise if the transaction ID:s should always be in item the problem with your code is likely outside of the code snippets you shared here. I would check what the ID:s are you are trying to look up and do a sanity check.
I have a SortedDictionary declared like such:
SortedDictionary<MyObject,IMyInterface> dict = new SortedDictionary<MyObject,IMyInterface>();
When its populated with values, if I grab any key from the dictionary and then try to reference it immediately after, I get a KeyNotFoundException:
MyObject myObj = dict.Keys.First();
var value = dict[myObj]; // This line throws a KeyNotFoundException
As I hover over the dictionary (after the error) with the debugger, I can clearly see the same key that I tried to reference is in fact contained in the dictionary. I'm populating the dictionary using a ReadOnlyCollection of MyObjects. Perhaps something odd is happening there? I tried overriding the == operator and Equals methods to get the explicit comparison I wanted, but no such luck. That really shouldn't matter since I'm actually getting a key directly from the Dictionary then querying the Dictionary using that same key. I can't figure out what's causing this. Has anyone ever seen this behavior?
EDIT 1
In overriding Equals I also overloaded (as MS recommends) GetHashCode as well. Here's the implementation of MyObject for anyone interested:
public class MyObject
{
public string UserName { get; set;}
public UInt64 UserID { get; set;}
public override bool Equals(object obj)
{
if (obj == null || GetType()!= obj.GetType())
{
return false;
}
// Return true if the fields match:
return this.Equals((MyObject)obj);
}
public bool Equals(MyObject other)
{
// Return true if the fields match
return this.UserID == other.UserID;
}
public override int GetHashCode()
{
return (int)this.UserID;
}
public static bool operator ==( MyObject a, MyObject b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.UserID == b.UserID
}
public static bool operator !=( MyObject a, MyObject b)
{
return !(a == b);
}
}
What I noticed from debugging is that if I add a quick watch (after the KeyNotFoundException is thrown) for the expression:
dict.ElementAt(0).Key == value;
it returns true. How can this be?
EDIT 2
So the problem ended up being because SortedDictionary (and Dictionary as well) are not thread-safe. There was a background thread that was performing some operations on the dictionary which seem to be triggering a resort of the collection (adding items to the collection would do this). At the same time, when the dictionary iterated through the values to find my key, the collection was being changed and it was not finding my key even though it was there.
Sorry for all of you who asked for code on this one, I'm currently debugging an application that I inherited and I didn't realize this was going on on a timed, background thread. As such, I thought I copied and pasted all the relevant code, but I didn't realize there was another thread running behind everything manipulating the collection.
It appears that the problem ended up being because SortedDictionary is not thread-safe. There was a background thread that was performing some operations on the dictionary (adding items to the collection) which seems to be triggering a resort of the collection. At the same time, when the dictionary was attempting to iterate through the values to find my key, the collection was being changed and resorted, rendering the enumerator invalid, and it was not finding my key even though it was there.
I have a suspicion - it's possible that you're changing the UserID of the key after insertion. For example, this would demonstrate the problem:
var key = new MyObject { UserId = 10 };
var dictionary = new Dictionary<MyObject, string>();
dictionary[key] = "foo";
key.UserId = 20; // This will change the hash code
var value = dict[key]; // Bang!
You shouldn't change properties involved in equality/hash-code considerations for an object which is being used as the key in a hash-based collection. Ideally, change your code so that this can't be changed - make UserId readonly, initialized on construction.
The above definitely would cause a problem - but it's possible that it's not the same as the problem you're seeing, of course.
In addition to overloading == and Equals, make sure you override GetHashCode with a suitable hash function. In particular, see this specification from the documentation:
If two objects compare as equal, the GetHashCode method for each object must return the same value. However, if two objects do not
compare as equal, the GetHashCode methods for the two objects do not
have to return different values.
The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state
that determines the return value of the object's Equals method. Note
that this is true only for the current execution of an application,
and that a different hash code can be returned if the application is
run again.
For the best performance, a hash function should generate an even distribution for all input, including input that is heavily clustered.
An implication is that small modifications to object state should
result in large modifications to the resulting hash code for best hash
table performance.
Hash functions should be inexpensive to compute.
The GetHashCode method should not throw exceptions.
I agree with Jon Skeet's suspicion that you're somehow unintentionally modifying UserID property after it's added as a key. But since the only property that's important for testing equality in MyObject is UserID (and therefore that's the only property that the Dictionary cares about), I'd recommend refactoring your code to use a simple Dictionary<ulong, IMyInterface> instead:
Dictionary<ulong, IMyInterface> dict = new Dictionary<string, IMyInterface>();
ulong userID = dict.Keys.First();
var value = dict[userID];
Subtitle: Can EventHandlerList key's Type be something else than object?
I wanted to use an enum store the keys I would like to have in an EventHandler.
public enum EventKey
{
OnBark, OnCry
}
public EventHandlerList EventList = new EventHandlerList();
public event ComplaintEventHandler OnBark
{
add
{
EventList.AddHandler(EventKey.OnBark, value);
}
remove
{
EventList.RemoveHandler(EventKey.OnBark, value);
}
}
var handler = EventList[eventKey] as ComplaintEventHandler;
>
handler = null
As it turns out it does not work. But it works if I use keys declared like (as shown on):
static object EventKeyOnTap = new object();
After reading some mscorlib's code I see that the problem comes from next.key == key in
private EventHandlerList.ListEntry Find(object key)
{
EventHandlerList.ListEntry next = this.head;
while (next != null && next.key != key)
{
next = next.next;
}
return next;
}
Both compared keys are from my Enum, but they are not equal!
I guess it comes from some implicit casts to object happening (the key stored in the list is of type object) but am not fluent enough with such low-level concepts.
Is my guess right?
What is the best way to use an Enum as a key in an EventHandlerList?
For now I will create my own EventHandlerList with Enum as key Type.
For now I created my own EventHandlerList with a constructor taking a Func<object, object, bool> which I then use in place of the equality comparaison aforementioned.
Try this code. Can you explain output?
var bark1 = (object)EventKey.OnBark;
var bark2 = (object)EventKey.OnBark;
Console.WriteLine(bark1 != bark2);
Console.WriteLine(bark1.Equals(bark2));
If yes, I don't know why you asked this question. If no, you definitely should get aware of value types, reference types and boxing.
In short, AddHandler method accepts object parameter, hence your key (which is value type) is boxed when you call:
EventList.AddHandler(EventKey.OnBark, value);
If you call this method twice with the same enum key, key will be boxed twice, and two different objects in heap will be actually created.
That's why this check next.key != key inside Find method fails (it compares addresses of two separate objects in heap).
EventHandlerList is sealed class, so you cannot affect its guts, but in your own code you could handle this situation with better check:
next.key.Equals(key)
I have a large C# (3.0) object structure originating from a deserialized XML document. I need to know whether a variable deep in the hierarchy is null. The way I do this now is to check every parent object on the way down for null, but this leads to a long repetition of if statements.
I am trying to avoid expensive try-catch blocks.
Is there a smarter way to do this?
edit:
For example after a deserialization of an XML application form into an object hierarchy structure there could potentially be a salary value under
applicationForm.employeeInfo.workingConditions.salary
but to find out safely I have to write something like
if (applicationForm.employeeInfo != null)
if (applicationForm.employeeInfo.workingConditions != null)
if (applicationForm.employeeInfo.workingConditions.salary != null)
because simply using the latter if-statement will of course fail if one of the parent objects is null.
So I am looking for any smarter way to handle this situation.
You've run into the classic situation where each step in A.B.C.D may yield null. Though this is a common scenario, surprisingly there's no common pattern for solving it, other then using a large if-statement with lots of or's (||).
If each step can return a different class, then there's a rarely used pattern that you can apply: Use a generalized generic extension method with method chaining.
A generalized extension method is not a fixed term but I use it here for emphasizing that the ext. method is applicable to almost all types of objects, hence generalized. According to Bill Wagner in Effective C#, this is bad design. But in some remote cases, like yours, you can use it as long as you know what you're doing and why.
The trick is simple: define a generic extension method and generalize it for all classes that have a default constructor. If the test fails (object is null), the method returns a new object of the same type. Otherwise, it will return the unchanged object itself.
Why is this a good approach for your scenario? Because you don't need to change any existing classes, because it's understandable and promotes readable code, because it keeps type safety (compile time errors instead of runtime errors) and it's simply more concise compared to other approaches.
// extension method:
public static class SomeExtentionMethods
{
public static T SelfOrDefault<T>(this T elem)
where T : class, new() /* must be class, must have ctor */
{
return elem ?? new T(); /* return self or new instance of T if null */
}
}
// your code now becomes very easily readable:
Obj someObj = getYourObjectFromDeserializing();
// this is it applied to your code:
var mySalary = applicationForm.SelfOrDefault().
employeeInfo.SelfOrDefault().
workingConditions.SelfOrDefault().
salary;
// now test with one if-statement:
if(mySalary.IsEmpty())
// something in the chain was empty
else
// all's well that ends well :)
The beauty of this approach is that it works with all types of classes (provided they have a ctor), including collections and arrays. If any step is an index step, it will still work (depending on the collection, an invalid index can return null, default or raise an exception):
var x =
someObj.SelfOrDefault()
.Collection.SelfOrDefault()
.Items[1].SelfOrDefault()
.Mother.SelfOrDefault()
.Father.SelfOrDefault();
Update: expanded a bit and added a more elaborate example
Update: renamed NotNull, which implies boolean, to SelfOrDefault, which follows LINQ's naming convention (FirstOrDefault etc) and implies what it does.
Update: rewritten and reorganized, made code more applicable, hoping to make it more understandable overall :)
Firstly, if you're repeating the logic in more than one place, encapsulate it in a method.
Secondly, you don't need lots of if statements, you just need one with a lot of OR conditions:
if(parent==null ||
parent.Child == null ||
parent.Child.GrandChild == null ...
Thirdly, "avoiding expensive try/catch blocks" may be a premature optimization, depending on your scenario. Have you actually tried this and profiled it, and is it really causing a large overhead?
You can nest ternary operators. Still a pain, but not as bad as nested ifs.
string salary = (applicationForm.employeeInfo == null) ? null :
(applicationForm.employeeInfo.workingConditions == null) ? null :
applicationForm.employeeInfo.workingConditions.salary;
If you just want to know whether or not it is null:
bool hasSalary = (applicationForm.employeeInfo == null) ? false :
(applicationForm.employeeInfo.workingConditions == null) ? false :
(applicationForm.employeeInfo.workingConditions.salary != null);
Here's my simple solution:
if (applicationForm?.employeeInfo?.workingConditions?.salary != null)
Here any of these objects (applicationForm, employeeInfo, workingConditions, salary) can be null and it will resolve without error.
can't you iterate?
for (SomeObject obj = someInstance; obj != null; obj = obj.Parent) {
//do something
}
Use reflection.
Create a helper method that takes a parent object and a hierarchical dot notated string for your property names. Then use PropertyInfo and use recursion to go down one property at a time each time checking for null and returning null if so, else continuing down the hierarchy.
Since you didn't provide all too many details I had to fill in alot of the blanks. Here is a psuo-codeish example of how you might accomplish this via recursion
public bool doesHierarchyContainANull(MyObject ParentObject)
{
if (ParentObject.getMemberToCheckForNull() == null)
return true;
else if (ParentObject.isLastInHierarchy())
return false;
return doesHierarchyContainANull(ParentObject.getNextInHierarchy());
}
I liked the answer by Pontus Bremdahl, but added some more detail for my uses.
Code:
/// <summary>
/// Get a member in an object hierarchy that might contain null references.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="source">Base object to get member from.</param>
/// <param name="getResult">Member path.</param>
/// <param name="defaultResult">Returned object if object hierarchy is null.</param>
/// <returns>Default of requested member type.</returns>
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult, TResult defaultResult)
{
// Use EqualityComparer because TSource could by a primitive type.
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return defaultResult;
try
{
return getResult(source);
}
catch
{
return defaultResult;
}
}
/// <summary>
/// Get a member in an object hierarchy that might contain null references.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="source">Base object to get member from.</param>
/// <param name="getResult">Member path.</param>
/// <returns>Default of requested member type.</returns>
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult)
{
// Use EqualityComparer because TSource could by a primitive type.
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return default(TResult);
try
{
return getResult(source);
}
catch
{
return default(TResult);
}
}
Usage:
// Only authenticated users can run this code
if (!HttpContext.Current.SafeGet(s => s.User.Identity.IsAuthenticated))
return;
// Get count limit from app.config
var countLimit = int.Parse(ConfigurationManager.AppSettings.SafeGet(
s => s.Get("countLimit"),
"100" // Default 100 if no value is present
));
// Is int 6 a class? Always no, but just to show primitive type usage.
var is6AClass = 6.SafeGet(i => i.GetType().IsClass);
Update
CSharp version 6 now has this built into it.
https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#null-conditional-operators
Null-conditional operators
Sometimes code tends to drown a bit in null-checking. The null-conditional operator lets you access members and elements only when the receiver is not-null, providing a null result otherwise:
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
The null-conditional operator is conveniently used together with the null coalescing operator ??:
int length = customers?.Length ?? 0; // 0 if customers is null
The null-conditional operator exhibits short-circuiting behavior, where an immediately following chain of member accesses, element accesses and invocations will only be executed if the original receiver was not null:
int? first = customers?[0].Orders.Count();
This example is essentially equivalent to:
int? first = (customers != null) ? customers[0].Orders.Count() : null;
Except that customers is only evaluated once. None of the member accesses, element accesses and invocations immediately following the ? are executed unless customers has a non-null value.
Of course null-conditional operators can themselves be chained, in case there is a need to check for null more than once in a chain:
int? first = customers?[0].Orders?.Count();
Note that an invocation (a parenthesized argument list) cannot immediately follow the ? operator – that would lead to too many syntactic ambiguities. Thus, the straightforward way of calling a delegate only if it’s there does not work. However, you can do it via the Invoke method on the delegate:
if (predicate?.Invoke(e) ?? false) { … }
We expect that a very common use of this pattern will be for triggering events:
PropertyChanged?.Invoke(this, args);
This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable.
CheckForNull(MyType element)
{
if(element.ChildElement != null)
{
CheckForNull(element.ChildElement);
}
else
{
Console.WriteLine("Null Found");
}
}
You need a recursive function to iterate through the structure and check each node and its children for null. I was working on a sample but IE crashed (typical!!). Will post one later.
Sample
You could do something as simple (assuming you only ever want to just check if the structure is valid) as this:
public void ValidateStructure()
{
Node root = // get the root node
try
{
ValidateChildren(root);
Console.WriteLine("All nodes are valid");
}
catch (NullReferenceException)
{
Console.WriteLine("Structure contained a null node.");
}
}
public void ValidateChildren(Node parent)
{
// an NullReferenceException would be raised here since parent would be null
foreach (var child in parent.Children)
{
ValidateChildren(child);
}
}
My solution would be something like:
public static TResult SafeGet<TSource, TResult>(this TSource source, Func<TSource, TResult> getResult) {
if (source == null)
return default(TResult);
try {
return getResult(source);
}
catch {
return default(TResult);
}
}
Usage:
Test myTestObject = null;
var myStringOrNull = myTestObject.SafeGet(x => x.test.test.test.mySring);
Use the Null monad. It can be in the same file or a different file so long as you using it.
public static class NullMonad {
public static TResult SelectMany<TIn, TOut, TResult>(this TIn #in, Func<TIn, TOut> remainder, Func<TIn, TOut, TResult> resultSelector)
where TIn : class
where TOut : class
where TResult : class {
var #out = #in != null ? remainder(#in) : null;
return #out != null ? resultSelector(#in, #out) : null;
}
}
Then you can use LINQ:
var salary = from form in applicationForm
from info in form.employeeInfo
from cond in info.workingConditions
select cond.salary
This will return the salary if it exists, or null if any of the prior statements result to null, without throwing an exception.
Is it that much better? No, just saves you the slightest bit of repetition, but it looks cool. It also avoids the overhead of creating all the unused "OrDefault" objects in the accepted answer.