-1

Why do the Dictionary methods return a null set when they fail?

If the answer is "what do you expect them to return???" I guess I was expecting an empty HashSet that I can run methods like Count or GetEnumerator on. Without getting an exception.

Maybe my question is really, should I catch an exception, make the return value not null and then return it?

I looked at this question but my dictionary is not null when I call Add(), Remove() or TryGetValue()

Yes this is for a programming assignment, but the data structure is my choice, to represent a graph using two ConcurrentDictionaries.

When a test runs:

DependencyGraph t = new DependencyGraph();
Assert.IsFalse(t.GetDependees("x").GetEnumerator().MoveNext());

My method runs:

    public IEnumerable<string> GetDependees(string s)
    {
        HashSet<String> valuesForKey = new HashSet<String>();
        dependeeGraph.TryGetValue(s, out valuesForKey);
        return valuesForKey;
    }

And when it hits .GetEnumerator().MoveNext() on the return value I get nullReferenceException.

Community
  • 1
  • 1
JimLohse
  • 1,209
  • 4
  • 19
  • 44
  • what's `DependencyGraph`? can't you modify it to return what *you* want? – Daniel A. White Feb 15 '16 at 13:37
  • My class, consists of two dictionaries and a size counter, and methods to add and remove nodes and edges to a graph ... yes, I can good point – JimLohse Feb 15 '16 at 13:38
  • 1
    This is known as the `TryParse` pattern. See [MSDN](http://msdn.microsoft.com/en-us/library/vstudio/ms229009%28v=vs.100%29.aspx) and this [SO question](http://stackoverflow.com/questions/17207712/when-to-use-try-in-a-method-name). – Genti Saliu Feb 15 '16 at 13:40
  • 1
    [MSDN Dictionary Tkey, TValue.TryGetValue Method](https://msdn.microsoft.com/en-us/library/bb347013(v=vs.110).aspx) have you read the documentation on how the method works..? that would have been my first place to check / start – MethodMan Feb 15 '16 at 13:42
  • I am surprised this was not a duplicate :) and ... @MethodMan this time I read them with my eyes open. Thanks everyone, I am not generally this unsophisticated but I must really look like a noob haha – JimLohse Feb 15 '16 at 13:43
  • A little bit of sour grapes about the DVs (not really) but [I don't get why questions like this get 170 UVs](http://stackoverflow.com/questions/1243717/how-to-update-the-value-stored-in-dictionary-in-c) I would appreciate any suggestions to improve, thanks! – JimLohse Feb 15 '16 at 16:44

2 Answers2

4

Oh boy...

Stop ignoring the return value. The return value tells you "there's no data available". The only reason the out parameter is set at all is because C# requires you to do that - you're not supposed to use that value.

If you don't care about the difference between "no data" and "a set with zero items", you can write your own extension method to simplify things:

public static IEnumerable<string> GetValueOrEmpty(this DependencyGraph dg, string s)
{
  HashSet<string> value;

  if (!dg.TryGetValue(s, out value)) return Enumerable.Empty<string>();

  return value;
}
Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Oh crap I am doing something really dumb to return the outValue, is that what you are saying? – JimLohse Feb 15 '16 at 13:39
  • 1
    @JimLohse Yeah; when `TryGet` returns false, just return something like `Enumerable.Empty()`. Just be glad `out` parameters are something defined in C# - C would just give you some random garbage instead of the (comparatively) pretty `null`. Note that you can write your own extension method that returns either `Enumerable.Empty()` or the value from the dictionary. – Luaan Feb 15 '16 at 13:40
  • D'oh thanks! I think this will be the accepted answer, the other answer is correct but doesn't direct me to a solution. Let me try this out. – JimLohse Feb 15 '16 at 13:41
  • Thanks for the edit, it answers the followup I was about to ask. Will accept when the timer runs out – JimLohse Feb 15 '16 at 13:46
2

TryGetValue has an out parameter for the TValue type parameter. Since out parameters must be initialised by the called function, TryGetValue must do this generically for every possible type. The only such value is default(TValue) which is null for reference types and 'zero' for value types.

Lee
  • 142,018
  • 20
  • 234
  • 287
  • I appreciate this explanation, at the moment I suspect Luaan's answer is more on target for the error in my thinking, gonna wait a few to see things settle before I decide what to accept. – JimLohse Feb 15 '16 at 13:41