Ienumerable Extension method for dictionary array calls
Im trying to get an enumberable collection from a dictionary held array. O开发者_如何学编程r should I say, I'm trying to write an extension method for my dictionary objects which store arrays to return an IEnumerable item when the result is null.
Im using dictionarys to store array datasets (there are speed reasons for this), which I extract at certain search points. the extracted data is used in Linq queries, joins etc but I have problems when a data set doesnt exist.
Returning an empty (0 count) row set would fix my problem. what I have so far is this (simplified code ofcourse)
public class Supplier
{
public string ID {get;set}
public string Name {get;set}
}
private sups[] = new Supplier[10];
Dictionary<int,Supplier[]> dic = new Dictionary<int, Supplier[]>();
dic.Add(1,sups[]);
public static IEnumerable<Supplier> TryGetValue<Tkey>(this IDictionary<Tkey, Supplier[]> source, Tkey ItemKey)
{
Supplier[] foundList;
IEnumerable<Supplier> retVal;
if (source.TryGetValue(ItemKey, out foundList))
{
retVal = foundList.AsEnumerable();
}
else
{
retVal = new Supplier[0].AsEnumerable();
}
return retVal;
}
// later in the code there is some thing like:
dic.TryGetValue(1).Count()
//or a linq join
from a in anothertable
join d in dic.TryGetValue(1) on a.ID equals d.ID
What im trying to acheive is a generic extension method like below:
public static IEnumerable<T> TryGetValue<Tkey,TValue>(this IDictionary<Tkey, TValue> source, Tkey ItemKey)
{
// same code...
// returning retVal = new T[0].AsEnumerable();
}
I keep getting close but never exactly there.... I would like to keep the extension method parameters simple. Its the passing of T which keeps catching me out.
If anybody can help then please send me your feed back.
many thanks in advance!
EDIT: Complications with type-inference.
Here's a way, the idea is to constrain the dictionary-values' type to be anIEnumerable
of something.
Unfortunately, type-inference doesn't seem to work with this signature (tested with C# 3), so you will have to specify the generic arguments explicitly.
public static IEnumerable<TUnderlyingValue> GetValueOrEmpty<TKey, TUnderlyingValue, TValue>
(this IDictionary<TKey, TValue> source, TKey key)
where TValue : IEnumerable<TUnderlyingValue>
{
if(source == null)
throw new ArgumentNullException("source");
TValue retVal;
return source.TryGetValue(key, out retVal) ? retVal : Enumerable.Empty<TUnderlyingValue>;
}
Usage:
var dict = new Dictionary<string, int[]>
{
{ "foo", new[] { 6, 7, 8 } }
{ "bar", new[] { 1 } }
};
var fooOrEmpty = dict.GetValueOrEmpty<string, int, int[]>("foo"); // { 6, 7, 8 }
var barOrEmpty = dict.GetValueOrEmpty<string, int, int[]>("bar"); // { 1 }
var bazOrEmpty = dict.GetValueOrEmpty<string, int, int[]>("baz"); // { }
Alternatively, we could use just 2 generic parameters without any constraints, but this will make the dictionary type less flexible. In this case, the compiler will infer the generic arguments just fine.
public static TUnderlyingValue[] GetValueOrEmpty<TKey, TUnderlyingValue>
(this IDictionary<TKey, TUnderlyingValue[]> source, TKey key)
{
if(source == null)
throw new ArgumentNullException("source");
TUnderlyingValue[] retVal;
return source.TryGetValue(key, out retVal) ? retVal : new TUnderlyingValue[0];
}
精彩评论