0

I can normally use the First() method in a Dictionary type variable like this,

Dictionary<string,string> dic = new Dictionary<string,string>();
dic.Remove(dic.First(kvp => kvp.Value == some_value).Key);

However, when I tried to inherit a class from Dictionary like below it's giving me an error.

class Dic : Dictionary<string, string>
{
   public void DoSomething()
   {
      Remove(First(kvp => kvp.Value == some_value).Key);
   }
}

Error Message This is the error I'm getting.

BTW, First() originates not from Dictionary

Originate

I have tried implementing IEnumerable but it did not help

NeWi-SL
  • 127
  • 1
  • 6
  • What is `dic` in `DoSomething` method? – Vivek Nuna Dec 11 '21 at 08:09
  • Sorry @viveknuna I have corrected it – NeWi-SL Dec 11 '21 at 08:14
  • Depending on you actual use case, deriving from Dictionary may not be a good decision. Prefer composition over inheritance, or use extension methods. Did you see this: https://stackoverflow.com/questions/1636885/remove-item-in-dictionary-based-on-value? – Klaus Gütter Dec 11 '21 at 08:20
  • [`First()`](https://learn.microsoft.com/dotnet/api/system.linq.enumerable.first) is an extension method defined in the [`System.Linq.Enumerable` `static` class](https://learn.microsoft.com/dotnet/api/system.linq.enumerable). You need a `using System.Linq;` directive for the compiler to find it; Visual Studio will suggest this fix when needed. – Lance U. Matthews Dec 11 '21 at 08:21
  • Thank you for your advices and suggestions. I will consider them for sure @LanceU.Matthews and Klaus – NeWi-SL Dec 11 '21 at 08:32
  • It is rare that one would need to inherit from anything in System.Collections.Generic; it's more likely that you would write a class that **has-a** generic collection, than **is-a** generic collection. What are you trying to do? See https://stackoverflow.com/questions/21692193/why-not-inherit-from-listt?rq=1 – Caius Jard Dec 11 '21 at 08:54
  • 1
    Just wanted to point out, that your dictionary seems to be the wrong way round.. If you're routinely removing by Value, you should consider either flipping the key and value over, or you should consider having a pair of dictionaries ("forward", and "reverse") so when you want to remove a forward Value X, you look up in reverse's Keys for X to get reverse's Value Y which is forward's Key. You, then remove from both dictionaries based on the Keys you now know (remove from reverse using Key X, remove from forward using Key Y) – Caius Jard Dec 11 '21 at 09:02
  • @CaiusJard I have another part in this code that requires accessing Value by the Key in the order I have declared the Dictionary here. So that, if I flip them over I will again need to use the same way to access the Value in that place. That's why. – NeWi-SL Dec 11 '21 at 09:13
  • @CaiusJard Why I am inheriting it is because I need to override the default `Add()` method to check whether the Value is already existing. – NeWi-SL Dec 11 '21 at 09:18
  • *I have another part in this code* and that's why I said have a pair. Searching by value is incredibly slow compared to searching by key; if your use case is 99% key lookup and 1% value lookup it might make sense but you should consider pairing – Caius Jard Dec 11 '21 at 09:26
  • @CaiusJard ah Ok I get your point. I will try doing it in that manner. Thanks a lot again for your explanation and help. – NeWi-SL Dec 11 '21 at 09:29

2 Answers2

1

Your Dic class won't compile as-is. You can use this instead of dic in the class.

class Dic : Dictionary<string, string>
{
    public void DoSomething()
    {
        Remove(this.First(kvp => kvp.Value == "some_value").Key);
    }
}

And then call like this: new Dic().DoSomething();

Steve Wong
  • 2,038
  • 16
  • 23
  • Thank You. It stopped giving me the error. Will try whether it works correctly – NeWi-SL Dec 11 '21 at 08:16
  • 1
    This would be a much better answer if you gave the reason for it: `First()` is an extension method, and extension methods can only be called on an explicitly specified instance. Therefore, this is one of the few cases where it is required to use `this` in accessing a method that (seemingly) belongs to the own class. – PMF Dec 11 '21 at 10:01
  • Thanks @PMF, spot on. – Steve Wong Dec 11 '21 at 17:31
1

Why I am inheriting it is because I need to override the default Add() method to check whether the Value is already existing. –

That's what the TryAdd method (either as an extension method or baked in depending on versions) is for. If TryAdd returns false, the value existed; it does not throw an error on duplicate add. You can also use ContainsKey and TryGetValue as alternative ways of checking if a key exists or not

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Thank you for answering. BTW I am just curious that are there any data types in C#.NET that supports having a unique key and a value and can remove items either by using key or value rather than just key as in a Dictionary? – NeWi-SL Dec 11 '21 at 09:36
  • 1
    I suppose, as your dictionary is a string string you don't have to pair it; you can just add your key and value each way round, and any removal retrieves tha value for the given key and removes the value as a key as well as a key. Two way dictionaries are talked about, but I don't know if an intrinsic implementation, particularly as having a pair of them seems reasonably easy to implement and isn't causing data duplication as it's just indexing two different references to the same data – Caius Jard Dec 11 '21 at 09:55