6

I'm looking to have a error raise to prevent a build if there are duplicate keys in my static Dictionary.

My current Dictionary below

public static readonly Dictionary<string, string> Fruits = new Dictionary<string, string>
{
    {"Sobeys", "Apples"},
    {"NoFrills", "Oranges"}
}

But lets say someone accidentally changes Sobeys to be Nofrills, I would like a compiler error to be raised to prevent anything to be done until that duplicate key is resolved. May I ask is that possible? If so how abouts would I do that?

public static readonly Dictionary<string, string> Fruits = new Dictionary<string, string>
{
    {"NoFrills", "Apples"},
    {"NoFrills", "Oranges"}
}
Master
  • 2,038
  • 2
  • 27
  • 77
  • 4
    You'll have to write your own compiler if you want it to have different behavior than the rules of C#. – Servy Aug 24 '16 at 20:37
  • 3
    Are you using Visual Studio 2015 or newer? If so it is possible with a custom [live code analyzer](https://msdn.microsoft.com/en-us/magazine/dn879356.aspx), but it is going to be a non trival amount of work to make it robust. – Scott Chamberlain Aug 24 '16 at 20:39
  • @Servy Since C# is open source, perhaps instead a patch should be submitted to the community. https://github.com/dotnet/roslyn – Kelson Ball Aug 24 '16 at 20:39
  • 1
    You also could fork [rosyln](https://github.com/dotnet/roslyn) instead of writing a compiler from scratch. – Blorgbeard Aug 24 '16 at 20:40
  • Such error is immediately caught by your unit tests that you run often/constantly (don't you?). Why would you need custom compiler for such case than? – Alexei Levenkov Aug 24 '16 at 20:49

4 Answers4

8

Nope, that's a runtime thing. As soon as the class is loaded into memory it will throw an exception (which are inherently runtime).

You could add a custom check through a diagnostic analyzer but that would be a lot of pain for very little gain. I suggest you just keep it as it is and keep an eye on any exceptions with a new deployment. You can always add a comment to make it clear to other devs that keys have to be unique but where do you stop? A developer is supposed to know basic framework rules like that.

You could also use, for example, an enum as the key which would make it clear at devtime when you try to add something that already exists. Another option is to refer to const string fields although it remains somewhat brittle.

Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
  • 2
    I pretty much would want to say the same thing as you, but the only thing I would add to it is this is a good job for Unit Tests to catch – Scott Chamberlain Aug 24 '16 at 20:44
  • @ScottChamberlain Unit Tests would help if the adding was done through a method but you can't unit test when it's already duplicated in the initialization of course – Jeroen Vannevel Aug 24 '16 at 20:47
  • @JeroenVannevel ? Accessing that property will fail with exception - so test using it will fail... Not sure why you would write test that succeeds when exception is thrown... – Alexei Levenkov Aug 24 '16 at 20:51
  • @AlexeiLevenkov I didn't mean that the test would succeed -- just that the test would never run because there'd be an exception immediately. But of course, now that I re-read it, that's exactly what Scott said ^^ – Jeroen Vannevel Aug 24 '16 at 20:54
7

You can also use the following hack (I do not recommend it): convert anonymous type to dictionary. Anonymous types do not allow duplicate property names.

Example:

Dictionary<string, string> Fruits = ToDictionary(
   new
   {
      Sobeys = "Apples",
      NoFrills = "Oranges"
   }
);

But this approach has the following limitation: you can have only valid identifiers as keys in your dictionary.

How to implement ToDictionary method is described there: In c# convert anonymous type into key/value array?

Community
  • 1
  • 1
just.ru
  • 648
  • 5
  • 12
1

C# compiler does not provide such possibility. You will get an Exception at runtime.

To solve this, you have to implement your own pre-processing checks or handle runtime exceptions.

Nazar
  • 624
  • 6
  • 7
0

I would like an compiler error to be raised

It is not an error. That's why the compiler wan't issue a compile-time error. Collection initializer are syntactic sugar and are translated into respective Add() method (or indexer in case of the alternate syntax) calls.

Your best option is to rely on some 3rd party code analysis tool that can spot such potential errors.

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90