-2

i have some letters in my config with x y coordinates. i want to add key + x + y to my dictionary, but i dont get it work...

example config:

c|1807|833

Code:

        private Dictionary<char, Tuple<int, int>> keyCoords;
...
     string[] lines = File.ReadAllLines(filePath);
                foreach (string line in lines)
                {
                    string[] parts = line.Split('|');
                    if (parts.Length != 3)
                    {
                        continue;
                    }

                    char key = parts[0][0];
                    int x = int.Parse(parts[1]);
                    int y = int.Parse(parts[2]);
                    keyCoords[key] = Tuple.Create(x, y);
                }

The last line keyCoords[key] = Tuple.Create(x, y); gives me a error:

The object reference was not set to an object instance.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Kalababu
  • 13
  • 2
  • 5
    Don't you forget to create keyCoords `keyCoords = new Dictionary>()`? – Sane Feb 07 '23 at 18:00
  • Also need to guard against an empty string in `parts[0]` – Joel Coehoorn Feb 07 '23 at 18:01
  • Finally, we can get this down to a one-liner. – Joel Coehoorn Feb 07 '23 at 18:05
  • While @JoelCoehoorn provided code that does what you need, the actual answer to why you get NRE is spelled out in default [What is NRE and how to fix it](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it), specifically in section "Collection/List/Dictionary" (also whole main answer the worth a good read at least once) – Alexei Levenkov Feb 07 '23 at 18:29

1 Answers1

0

We can get this down to a one-liner:

private Dictionary<char, (int, int)> keyCoords;
...

keyCoords = File.ReadLines(filePath).
               Select(line => line.Split('|')).
               Where(p => p.Length == 3).
               ToDictionary(k => k[0][0], v => (int.Parse(v[1]), int.Parse(v[2])));

This solves the problem in the question by ensuring we never reference any members of the keyCoords variable before the object is created.

Note there is a subtle difference from the original, in that this will replace anything in keyCoords, where the original could have appended data. But if that were a likely situation we wouldn't have the null referece exception in the first place.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 2
    Wow, I've never seen anyone leave the _dot_ trailing the previous fluent bit on the previous line like a period in a sentence (or a COBOL program) and then start the next line with a capital letter. It's appealing in an English language sort of way, but still disconcerting. – Flydog57 Feb 07 '23 at 18:22
  • Note that while useful and compact this code will throw on duplicate keys (unlike one in the question), if that is important. Consider ToLookup (https://stackoverflow.com/questions/5659066/what-is-the-difference-between-linq-todictionary-and-tolookup) or separately guarding against duplicates (there are plenty of questions showing all sorts of ways to do that). – Alexei Levenkov Feb 07 '23 at 18:32
  • @Flydog57 It comes from also needing to work in VB.Net from time to time. Since VB.Net doesn't have line terminators, it needs to end the line on a binary operator like `.`, so the compiler can know to expect the statement to continue on the next line without the special `_` character. I know it's not exactly idiomatic for C#, but go back and forth often and enough and this kind of pattern works its way into your flow. For example, I also tend to C#'s `+` string concatenation when working in VB instead of the native `&`. – Joel Coehoorn Feb 07 '23 at 19:42