3

I am trying to make Dictionary case insensitive. But, I declare it as a property, how can I make that insensitive.

I know that while defining, I can use it like :

var dict = new Dictionary<string, YourClass>(
        StringComparer.InvariantCultureIgnoreCase);

But, I am defining it in my interface and class respectively like

IDictionary<string, string> dict { get; }
public Dictionary<string, string> dict { get; set; }

How can I make this case insensitive ?

demo999 89
  • 105
  • 1
  • 8

4 Answers4

4

You mentioned that You define it in Your class like:

public Dictionary<string, string> dict { get; set; }

So, instead of using short form for auto properties, use the full form:

Dictionary<string, string> _dict = new Dictionary<string, string>(
    StringComparer.InvariantCultureIgnoreCase);
public Dictionary<string, string> dict
{
    get { return _dict; }
    set { _dict = value; }
}

If You are using C# 6.0, You could also probably even write it using the new auto property initializers syntax:

public Dictionary<string, string> dict { get; set; } = new Dictionary<string, string>(
    StringComparer.InvariantCultureIgnoreCase);

Links:

Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • But in interface, I cant do this way – demo999 89 Jul 27 '16 at 21:27
  • I'm not sure I understand the issue. An interface is only some description of public functionality made available by the class that implements it. So, when You use the interface, is it Your class that implements it? If so, the dictionary is created in the class and You don't have to create it again in the interface. – Lukasz M Jul 27 '16 at 21:32
  • If You would like to enforce the property to be case insensitive for any class that implements Your interface, You could create an inherited class, as suggested by @Scott Chamberlain in his answer. This, however, enforce associated classes to be changed to use the new case insensitive dictionary type. – Lukasz M Jul 27 '16 at 21:37
4

The only way you could enforce it on the class or interface level is you make a new derived type and use that type.

public class CaseInsensitiveDictionary<TValue> : Dictionary<string, TValue>
{
    public CaseInsensitiveDictionary() : base(StringComparer.InvariantCultureIgnoreCase)
    {
    }
}

Then in your interface you would do

CaseInsensitiveDictionary<YourClass> { get; }
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • This would work if your problem is related to how you are declaring your dictionaries. If you want to be able to arbitrarily change your dictionaries' case sensitivity at runtime based on some criteria, you aren't going to be able to do that without implementing a lot of things on your own. – Robert Columbia Jul 27 '16 at 21:31
1

You can't. The comparer is a read-only property (https://msdn.microsoft.com/en-us/library/ms132092(v=vs.110).aspx). Declare your comparer during the construction of your object.

Allowing one to change comparers at runtime would be seriously problematic as it could result in sudden key collisions that would require the dictionary to be restructured.

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
0

If the case insensitivity is intended to be part of the contract, it sounds like what you really want to be doing is encapsulating this logic inside something else and then exposing that on your interface instead.

Depending on what specific functionality you're trying to expose, something as simple as this might do the trick:

public class CaseInsensitiveIndex
{
    private readonly Dictionary<string, object> _collection = 
        new Dictionary<string, object>();

    public object this[string index]
    {
        get { return _collection[index.ToLower()]; }
        set { _collection[index.ToLower()] = value; }
    }
}

public interface IHasCaseInsensitiveIndex
{
    CaseInsensitiveIndex Index { get; }
}

It seems a little odd to me to be publicly exposing a collection via an interface like this (this feels like it should be an internal implementation detail... but that depends on the context - consider whether your encapsulation needs work) but this is the closest thing to what you're trying to achieve that I can think of.

Ant P
  • 24,820
  • 5
  • 68
  • 105