I have Dictionary<Predicate<double>, SomeEnum>
:
var dic = new Dictionary<Predicate<double>, SomeEnum>
{
{ (d) => d < 10, SomeEnum.Foo },
{ (d) => d > 90, SomeEnum.Bar }
};
I want to call TryGetValue(K, out V)
against it like this:
dic.TryGetValue(99)
and receive
SomeStruct.Bar
But first param for TryGetValue()
is Predicate<T>
, not just T
. How can I do what I want?
I found only a dirty workaround:
var kpv = dic.FirstOrDefault(p => p.Key(99));
if (kpv.Key != null)
var result = kpv.Value;
Are there other ways?
Or how to implement my idea properly? - declare a key not as a constant but like a segment.
There are a couple of things wrong here:
Predicate<double>
is not an appropriate type to use as a TKey
. The key for a dictionary is supposed to identify a value, not calculate a value.
This wouldn't make any sense using lambdas either. Because they are anonymous, you wouldn't get any equivalence, and won't be able use a dictionary.
See this code sample for an illustration:
Predicate<double> fn_1 = d => d == 34.0d;
Predicate<double> fn_2 = d => d == 34.0d;
// Note: There are not equal
if (fn_1 == fn_2)
Console.WriteLine("These are Equal?");
If anything, you could use a list of delegates and execute each one to find the ones that match, but at that point you must expect multiple results. If you only want to get a single result, then you have to consider which order the predicates are stored within your list.
Don't misuse KeyValuePair
as a hack for not having Tuple<T1,T2>
. It would be fairly easy to create a class that has both a Predicate and a SomeStruct. Look:
public class MySegment
{
public Predicate<double> Predicate {get;set;}
public SomeStruct Result {get;set;}
}
To go through a sequence of predicates, and find the matching ones would look like this:
...
List<MySegment> list = new List<MySegment>();
...
list.Add(new MySegment { Predicate = d => d < 10, Result = SomeStruct.Foo });
list.Add(new MySegment { Predicate = d => d > 90, Result = SomeStruct.Bar });
...
public IEnumerable<SomeStruct> GetResults(double input)
{
foreach (var item in list)
if (item.Predicate(input))
yield return item.Result;
}