Question Generic Dictionaries

zeinab mokdad

Member
Joined
Dec 23, 2021
Messages
13
Programming Experience
5-10
Dears, when wrtitng this generic class
C#:
public static R GetValueFirstItem<T, Q, R>(this Dictionary<T, Q> dict, T key)
    where Q : IEnumerable<R>
{
    if (!dict.TryGetValue(key, out var r))
        return default(R);

    if (r == null || r.Count() == 0)
        return default(R);

    return r.ElementAt(0);
}

Dictionary<string, List<OrderItemInProcess>> orderItemsByType;
var activateConnectivity = orderItemsByType.GetValueFirstItem(ActivateConnectivity);
var addPathResource = orderItemsByType.GetValueFirstItem<string, List<OrderItemInProcess>, OrderItemInProcess>(AddPathResource);
when trying to call this class var activateConnectivity = orderItemsByType.GetValueFirstItem(ActivateConnectivity); will raise and error while var addPathResource = orderItemsByType.GetValueFirstItem<string, List<OrderItemInProcess>, OrderItemInProcess>(AddPathResource);
can someone explain why is that , and what can we do to prevent this ?
 
Last edited by a moderator:
You cannot infer a generic type parameter through a constraint the way you're trying to. The constraint is used to check for validity so there has to be something to check against. That means that, in order to check that type Q actually does implement IEnumerable<R> you have to know what type R is. If it can't be inferred from the method signature, which it can't, then you have to specify it when you call it.
 
Then when I specify hat R is it should work,
but when trying this code:

C#:
public class OrderItemInProcess{}

public static class Extension
{
public static R GetValueFirstItem<T, Q, R>(this Dictionary<T, Q> dict, T key) where R : OrderItemInProcess where Q : IEnumerable<R>
{
if (!dict.TryGetValue(key, out var r))
return default(R);

if (r == null || r.Count() == 0)
return default(R);

return r.ElementAt(0);
}
}

and trying to call it this way
C#:
Dictionary<string, IEnumerable<OrderItemInProcess>> orderItemsByType = new Dictionary<string, IEnumerable<OrderItemInProcess>>();
OrderItemInProcess x = orderItemsByType.GetValueFirstItem("");
it also raise an error
 
Last edited by a moderator:
The compiler is not yet that smart to make that inference between the types. I think enough parts of the compiler are now open source, you could fork the code, modify it, and submit a patch that would do that inference.
 
You could do this:
C#:
public static R GetValueFirstItem2<T, R>(this Dictionary<T, IEnumerable<R>> dict, T key) where R : class
    =>  dict.TryGetValue(key, out var r) ? r?.FirstOrDefault() : default;
Then both T and R is inferred from input.
 
this doesn't work with List
C#:
var orderItemsByType = new Dictionary<string, List<OrderItemInProcess>>();
var addPathResource = orderItemsByType.GetValueFirstItem2("");
 
Last edited by a moderator:
this doesn't work with List
var orderItemsByType = new Dictionary<string, List<OrderItemInProcess>>(); var addPathResource = orderItemsByType.GetValueFirstItem2("");
It will work if you add List<T> objects to the Dictionary as long as the type of the Dictionary itself specifies IEnumerable<T>. The fact that you want to be able to do something does not mean that there is a way. If you want to be able to use the types you are, you need to specify the generic type parameters explicitly when you call the method.
 
I know that , but I am searching if there is another way ,an easier way to do that, a way that I am not aware of. and in addition I want some explanations
As I mentioned in my first post
 
I know that , but I am searching if there is another way
That doesn't make sense. I said that it can't be done and you say you know that, but you're looking for a way to do it. If you know it can't be done then looking for another way makes no sense. If you believe that there may be another way then you don't know that it can't be done. I'm not saying don't ask the question but you asked it and it has been confirmed that it can't be done and that you must specify the types explicitly. Am I not allowed to say that for some reason? Would you rather remain ignorant of the fact?
 
Back
Top Bottom