How to deal specifically with a Keynotfoundexception?

Asked

Viewed 80 times

2

I have a doubt, I tried to find some content on Google but I did not find.

I have a block try catch as follows:

try
{
    //código
    string idFormaPgto = Dictionaries.FormaPgto[_order.FK_PEDIDOS_FORMA_PAGAMENTO];
    //restante do código
}
catch(Exception e)
{

}

The problem is sometimes I’ll get one KeyNotFoundException but the following code MUST continue and I need to set a standard vallor to idFormaPgto, I don’t know if there’s a more elegant and correct way to treat this, what I thought was:

try
{
    //código
    string idFormaPgto = "";
    try
    {
       idFormaPgto = Dictionaries.FormaPgto[_order.FK_PEDIDOS_FORMA_PAGAMENTO];
    }
    catch(Exception e)
    {
       idFormaPgto = "1"; //tratamento do idFormaPgto 
    }
    //restante do código
}
catch(Exception e)
{

}

My code solves the problem, but I believe it is not the most correct way to do this, perhaps using some class extension method Dictionary but I don’t know any. The goal is to treat this KeyNotFoundException unused try catch inside try catch

  • But the other catch will do something?

  • Go, is that so... will be several queries within the main catch, some queries may result in Exception others not, for example this call in Dictionary can’t fall in the main catch, the others yes, so I’m treating her in specific, but I think it’s "pork"

  • It seems to me that the appropriate treatment would be for you to catch the exception you already expect... in case the KeyNotFoundException

  • So why not check if the key exists before using?

  • @LINQ is a possible solution, but did not want to use blocks, like Try catch, if Else or whatever knows ? Do you know any function in the style "If there is no return this" all in one line ? as if it were a Firstordefault

  • 1

    @Leonardobonetti I know, I’ll try to write to you =)

  • @LINQ Okay, no waiting

  • I will improve the response with examples as soon as possible. Now I need to run to a meeting.

Show 3 more comments

3 answers

5


You can simply use the method TryGetValue. This method attempts to get the value by the given key and, if the key does not exist, returns the type pattern.

string idFormaPgto;
Dictionaries.FormaPgto.TryGetValue[_order.FK_PEDIDOS_FORMA_PAGAMENTO, out idFormaPgto];

If you want to shorten a little more idea and make it more like the method FirstOrDefault from LINQ, it is possible to write an extension method for dictionaries.

For example:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var dicio = new Dictionary<int, string>
        {
            { 65, "A" },
            { 74, "J" },
            { 69, "E" }
        };

        Console.WriteLine(dicio.GetByKeyOrDefault(65) ?? "Chave inexistente");
        Console.WriteLine(dicio.GetByKeyOrDefault(80) ?? "Chave inexistente");
        Console.WriteLine(dicio.GetByKeyOrDefault(69) ?? "Chave inexistente");
    }
}

public static class DictionaryExtensions
{
    public static TValue GetByKeyOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
        => dict.ContainsKey(key) ? dict[key] : default(TValue); 
}

See working on . NET Fiddle

Note that in the implementation of the method, GetByKeyOrDefault it is still possible to do one more micro-optimization and use the method TryGetValue not to need to make two queries in the dictionary (one in the method ContainsKey and another when obtaining the value).

  • I create a new class or insert this method somewhere?

  • I confess that I do not understand how happened this extension of the method in class Dictionary... how the compiler knows it is for the class Dictionary in particular? (I am thinking of creating a question for this)

  • It’s tied to the class name DictionaryExtensions ?

  • @Leonardobonetti By the first parameter. Note the keywork this before it. What happens is that the compiler changes the call to DictionaryExtensions.GetByKeyOrDefault(dicio, 65). This is precisely one of the bases of the operation of LINQ.

  • You have a question about that https://answall.com/q/136913/18246

3

You can simply use the Linq, as in the example below:

var dicionario= new Dictionary<string, string> {
    { "teste 1", "1" },
    { "testando", "2" },
};

var idFormaPgto = dicionario.SingleOrDefault(x=> x.Key.Equals(_order.FK_PEDIDOS_FORMA_PAGAMENTO)).Value ?? "1";

Edit As argued in the comments this is a basic approach and should only be considered in a point application. It is important to pay attention to the observations made by

Linq: That way you lose all idea of using a dictionary. The method Singleordefault will get an enumerator, move it item by item and do the validation of each of them. You simply throw out the main reason for a dictionary which is to have search complexity O(1) and passes to have search complexity O(N)

  • I like that solution, I’ll test it

  • @Leonardobonetti, I shortened it a little by removing the Where and passing the predicate directly to the SingleOrDefault()

  • Perfect ! all solutions were good, but this 11/10

  • That way you lose all idea of using a dictionary. The method SingleOrDefault will get an enumerator, move it item by item and validate each of them. You simply throw away the main reason for a dictionary which is to have search complexity O(1) and becomes complex search O(N).

  • @Leonardobonetti, just like Linq said. The best approach is the extension method that Linq presented, my answer should be considered only as a point outline for that piece of code. Follow with the other proposal, because you will be implementing this resource for all dictionaries, really extracting the performance that should have led to choosing them in its structure.

  • OK people, I will follow the guidance of both then, I ended up choosing the solution of @Leandroangelo because it seems easier to implement because I do not need to create another class and etc... but better understanding the correct and reusable way is really the LINQ.

Show 1 more comment

1

You can use the method Containskey, in which you pass the key who is searching and will be returned whether or not she exists in your collection Dictionary.

string idFormaPgto = "1";

//Se a key existir no seu Dictionary nós iremos pegar o valor, senão iremos manter o valor 1
if (Dictionaries.ContainsKey[_order.FK_PEDIDOS_FORMA_PAGAMENTO])
      idFormaPgto = Dictionaries[_order.FK_PEDIDOS_FORMA_PAGAMENTO];

If you want to do with a ternary condition it would be as follows:

    string idFormaPgto = Dictionaries.ContainsKey[_order.FK_PEDIDOS_FORMA_PAGAMENTO] ? Dictionaries[_order.FK_PEDIDOS_FORMA_PAGAMENTO] : "1";
  • Pedro, at first I would like a solution without blocks to not pollute too much the code inside the main catch Try, but anyway I will test.

  • uses a ternary operator

  • Then use ternary form: idFormaPgto = Dictionaries.FormaPgto.Containskey(_order.FK_PEDIDOS_FORMA_PAGAMENTO) ? Dictionaries.Formapgto[_order.FK_PEDIDOS_FORMA_PAGAMENTO] : "1";

  • You can even create an extension to be reusable

Browser other questions tagged

You are not signed in. Login or sign up in order to post.