Refactor this C# code to a more elegant version - c#

I am trying to refactor this code into a more elegant version. Can anyone please help.
The issue is where to as sign the first evaluation result for comparision later on?
And I want to eliminate the use of if/switch if possible
Should I remove Operator class and split Eval into And and Or class, but wouldn't be too much differnt I think
public interface IEval<T>
{
Func<T, bool> Expression { get; }
Operator Operator { get; }
string Key { get; }
}
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
var returnResult = true;
var counter = 0;
foreach (var condition in conditions)
{
var tempResult = condition.Expression(o);
if (counter == 0) //don't like this
{
returnResult = tempResult;
counter++;
}
else
{
switch (condition.Operator) //don't like this
{
case Operator.And:
returnResult &= tempResult;
break;
case Operator.Or:
returnResult |= tempResult;
break;
default:
throw new NotImplementedException();
}
}
}
return returnResult;
}
Thanks!
Code Updated:
public interface IEval<T>
{
Func<T, bool> Expression { get; }
bool Eval(bool against, T t);
}
public class AndEval<T> : IEval<T>
{
public Func<T, bool> Expression { get; private set; }
public AndEval(Func<T, bool> expression)
{
Expression = expression;
}
public bool Eval(bool against, T t)
{
return Expression.Invoke(t) & against;
}
}
public class OrEval<T> : IEval<T>
{
public Func<T, bool> Expression { get; private set; }
public OrEval(Func<T, bool> expression)
{
Expression = expression;
}
public bool Eval(bool against, T t)
{
return Expression.Invoke(t) | against;
}
}
public static class EvalExtensions
{
public static bool Validate<T>(this T t, IList<IEval<T>> conditions)
{
var accumulator = conditions.First().Expression(t);
foreach (var condition in conditions.Skip(1))
{
accumulator = condition.Eval(accumulator, t);
}
return accumulator;
}
}

Try this (assuming that conditions is not empty)
var accumulator = conditions.First().Expression(0);
foreach (var condition in conditions.Skip(1))
{
accumulator = condition.Operation.Evaluate(
condition.Expression(0), accumulator);
}
class AddOperation : Operation
{
public override int Evaluate(int a, int b)
{
return a & b;
}
}
You get the idea. You can make it even more compact by defining a method in condition that makes it run Expression() on itself and pass the result as the first argument to Evaluate:
condition.Evaluate(accumulator);
class Condition
{
public int Evaluate(int argument)
{
return Operation.Evaluate(Expression(0), argument);
}
}
(also an unrelated advice: never ever call a variable tempSomething, it is bad karma and creates the impression that you don't know exactly the role of that particular variable for the reader)

One general pattern for eliminating if/switch is to place the logic behind the if in the class you are operating on. I don't know enough about your domain to judge whether that will work here.
To apply that pattern, IEval would be expanded with another method, e.g.
IEval<T>.PerformOperation(T tempResult)
Each concrete implementation of IEval would then implement PerformOperation based on the specific operation it models, rather than using an Enum to indicate the type of operation.
(not sure if tempResult is of type T based on your code).
Then instead of the switch, write
returnResult = condition.PerformOperation(tempResult);

I would go with LINQ methods. Like -
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
return conditions
.Skip(1)
.Aggregate(
conditions.First().Expression(o),
(a, b) => b.Operator == Operators.Or ? (a || b.Expression(o)) : (a && b.Expression(o))
);
}
Or if you don't like ternary operator or need more extensible and nicer approach, you can use Dictionary to store and lookup functions associated with operators.
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
return conditions
.Skip(1)
.Aggregate(
conditions.First().Expression(o),
(a, b) => operators[b.Operator](a, b.Expression(o))
);
}
public static Dictionary<Operator, Func<bool, bool, bool>> operators = new Dictionary<Operator, Func<bool, bool, bool>>()
{
{Operator.And, (a, b) => a && b},
{Operator.Or, (a, b) => a || b}
}

The only thing I can think of is:
Have an if statement with checks that you have at least 2 conditions.
Then, instead of a foreach, use a regular for statement with a counter that starts at the second condition.
If you have zero conditions, return true. depending on your other business logic.
If you have one condition, then take the value.
Regardless, I believe the switch statement for the operation to perform is going to be necessary... Unless you change the code to execute some type of script which is your actual op to perform. Which I think is worse.

The only thing I don't like is that you have a variable called counter that will always be either 0 or 1. I'd make it a bool isFirst instead. If you want to get rid of the switch, you could replace your IEval interface with
public interface IEval<T>{
Func<T, bool> Expression { get; }
Func<bool, bool, bool> Combinator { get; }
string Key { get; }
}
Your Combine method will then be either
public Func<bool, bool, bool> Combinator {
get { return (b1, b2) => b1 | b2; }
}
or
public Func<bool, bool, bool> Combinator {
get { return (b1, b2) => b1 & b2; }
}
depending on the desired operation.
Might be overkill to return a delegate, though, perhaps just add a method bool Combine(bool value1, bool value2)

The following algorithm exhibits short-circuiting (it stops evaluating once the condition is known to be false). It has the same basic design, but it effectively uses an implicit true && ... at the beginning to make things cleaner.
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
bool result = true;
Operator op = Operator.And;
var conditionIter = conditions.GetEnumerator();
while (result && conditionIter.MoveNext())
{
bool tempResult = conditionIter.Current.Expression(o);
switch (op)
{
case Operator.And:
result &= tempResult;
break;
case Operator.Or:
result |= tempResult;
break;
default:
throw new NotImplementedException();
}
op = condition.Operator;
}
return result;
}

Related

Increment value from expression

I want to write a closure and increment it's value but i'm not able to do it. Here is my code
int i = 0;
Expression<Func<bool>> closurExpression = () =>
{
i++;
return i != 0;
};
but i get multuple errors about A lambda expression with a statement body cannot be converted to an expression tree or An expression tree may not contain an assignment operator etc. Is it possible without using external tools as Mono.Cecil etc?
for the question: why am I asking for it. I want to write a simple wrapper (for a signature Func<T,T> at least that will calculate count of calls. For example:
Wrapper<int> wrapper = () => 5;
for(int i = 0; i < 10; i++)
wrapper();
int calls = wrapper.Calls; // 10;
my first realisation was:
class FunctionWithCounter<T, TResult>
{
private readonly Func<T, TResult> function;
public int Calls { get; set; }
private FunctionWithCounter(Func<T, TResult> function)
{
Calls = 0;
this.function = function;
}
public static implicit operator FunctionWithCounter<T, TResult>(Func<T, TResult> func)
{
return new FunctionWithCounter<T, TResult>(func);
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg);
}
}
}
but after i get that recurcive functions won't work properly. For example for this code
int fact(int n) { return n < 2 ? 1 : n * fact(n - 1); }
Calls count will be 1 for any n. So idea is: get source function, and inject increment of Calls for every call of method increment it. All inner calls of method somefunc should be replaced by our method funcWithInjection, in this case we'll catch recursive functions too. Here is my code, but it doesn't work (except inject, so this code really increments a field value, but I cannot add source's method body to the tail and compile it, you can play with it if you will):
public class FunctionWithCounter<T, TResult> where T : new()
{
private readonly Func<T, TResult> _functionWithInjection;
private int _calls;
public int Calls
{
get
{
return _calls;
}
}
public FunctionWithCounter(Func<T, TResult> function)
{
_calls = 0;
var targetObject = function.Target ?? new object();
var dynMethod = new DynamicMethod(new Guid().ToString(), typeof(TResult), new[] { targetObject.GetType(), typeof(T), typeof(FunctionWithCounter<T, TResult>) }, true);
var ilGenerator = GenerateInjection(dynMethod);
ilGenerator.Emit(OpCodes.Ret);
var resDelegate = dynMethod.CreateDelegate(typeof(Func<T, FunctionWithCounter<T, TResult>, TResult>), targetObject);
var functionWithInjection = (Func<T, FunctionWithCounter<T, TResult>, TResult>)resDelegate;
var targetMethodBody = function.Method.GetMethodBody();
Debug.Assert(targetMethodBody != null, "mbody != null");
//here i need to write method body in the tail of dynamic method.
_functionWithInjection = function;
_functionWithInjection = t =>
{
functionWithInjection(t, this);
return default(TResult);
};
//finally here should be _functionWithInjection = t => functionWithInjection(t, this);
}
private ILGenerator GenerateInjection(DynamicMethod method)
{
var callsFieldInfo = GetType().GetField("_calls", BindingFlags.NonPublic | BindingFlags.Instance);
Debug.Assert(callsFieldInfo != null, "callsFieldInfo != null");
var ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Nop);
ilGenerator.Emit(OpCodes.Ldarg_2);
ilGenerator.Emit(OpCodes.Dup);
ilGenerator.Emit(OpCodes.Ldfld, callsFieldInfo);
ilGenerator.Emit(OpCodes.Ldc_I4_1);
ilGenerator.Emit(OpCodes.Add);
ilGenerator.Emit(OpCodes.Stfld, callsFieldInfo);
return ilGenerator;
}
public static implicit operator FunctionWithCounter<T, TResult>(Func<T, TResult> func)
{
return new FunctionWithCounter<T, TResult>(func);
}
public TResult this[T arg]
{
get
{
return _functionWithInjection(arg);
}
}
}
My second realisation was based on Emit API, but it's too complex and It was unfinished for a long time...
So now this is my 3rd try and i want to use expressions. Шt should look something like this:
public FunctionWithCounter(Expression<Func<T, TResult>> function)
{
Action action = () => _calls++;
Expression<Action> closurExpression = () => action();
var result = Expression.Block(closurExpression, function);
_functionWithInjection = Expression.Lambda<Func<T,TResult>>(result).Compile();
}
sorry for my english, but i really want to realize this idea
Well, you can do sidestep the rules using Interlocked.Increment:
int i = 0;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
... but I would be very cautious about doing so. I wouldn't expect many pieces of code which deal with expression trees to handle this terribly cleanly, given the side-effect involved.
The above does seem to work, in terms of behaving how I'd expect it to:
int i = -2;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
var del = expression.Compile();
Console.WriteLine(del()); // True
Console.WriteLine(del()); // False
Console.WriteLine(del()); // True
Console.WriteLine(del()); // True
Console.WriteLine(i); // 2
I think that your first approach was cleaner and ok for simple, non-recursive cases.
If you allow your wrapped functions to be aware of recursion, you can take it a little further and make the wrapper an argument to the function itself:
class RecursiveFunctionWithCounter<T, TResult>
{
private readonly Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function;
public int Calls { get; set; }
public RecursiveFunctionWithCounter(Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function)
{
Calls = 0;
this.function = function;
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg, this);
}
}
}
And use it like this:
var rw = new RecursiveFunctionWithCounter<int, int>(
(n, self) => { return n < 2 ? 1 : n * self[n - 1]; }
);
int rr = rw[3]; // rr=6
int rc = rw.Calls; // rc=3
On the other hand, if what you really want to do is instrument some existing methods in your code, consider doing a little Aspect Oriented Programming (with PostSharp for instance, this is an example of an aspect that increments a performance counter on each method call). This way you could just add an attribute like IncrementPerformanceCounterAttribute to your methods and the AOT library will do the rest.

Dynamic If Statement - Complex Filtering

I have a C# project that allows users to create filters on data using Regular Expressions. They can add as many filters as they want. Each filter consists of a Field and a regular expression that the user types in.
Right now it works with all AND logic. I loop through each filter and if it doesn't match I set skip = true and break out of the loop. Then if skip == true I skip that record and don't include it. So each and every filter must match in order for the field to be included.
However, now they want the ability to add more complex logic rules. So for example if they have created 4 filter rules. They want to be able to specify:
1 AND 2 AND (3 OR 4)
or they may want to specify
1 OR 2 OR 3 OR 4
or they may want to specify
(1 AND 2 AND 3) OR 4
and so on...I think you get the point.
I have added a textbox where they can type in the logic that they want.
I have been racking my brain and I am stumped on how to make this work. My only conclusion is to somehow be able to create a dynamic IF statement that is based on the text they type into the textbox but I don't know if that is even possible.
It seems like there should be an easy way to do this but I can't figure it out. If anyone could help me, I would really appreciate it.
Thanks!
Here's a full test that works as you want it with regular expressions and AND, OR and brackets. Note that this only supports the operators AND and OR and parentheses ( and ) and expects the input to be somewhat well formed (regular expressions must not have spaces). The parsing can be improved, the idea remains the same.
Here is the overall test:
var input = ".* AND [0-9]+ AND abc OR (abc AND def)";
var rpn = ParseRPN(input);
var test = GetExpression(new Queue<string>(rpn.Reverse())).Compile();
test("abc"); // false
test("abc0"); // true
test("abcdef"); // true
Here is the parsing to reverse polish notation:
public Queue<string> ParseRPN(string input)
{
// improve the parsing into tokens here
var output = new Queue<string>();
var ops = new Stack<string>();
input = input.Replace("(","( ").Replace(")"," )");
var split = input.Split(' ');
foreach (var token in split)
{
if (token == "AND" || token == "OR")
{
while (ops.Count > 0 && (ops.Peek() == "AND" || ops.Peek() == "OR"))
{
output.Enqueue(ops.Pop());
}
ops.Push(token);
}
else if (token == "(") ops.Push(token);
else if (token == ")")
{
while (ops.Count > 0 && ops.Peek() != "(")
{
output.Enqueue(ops.Pop());
}
ops.Pop();
}
else output.Enqueue(token); // it's a number
}
while (ops.Count > 0)
{
output.Enqueue(ops.Pop());
}
return output;
}
And the magic GetExpression:
public Expression<Func<string,bool>> GetExpression(Queue<string> input)
{
var exp = input.Dequeue();
if (exp == "AND") return GetExpression(input).And(GetExpression(input));
else if (exp == "OR") return GetExpression(input).Or(GetExpression(input));
else return (test => Regex.IsMatch(test, exp));
}
Note this does rely on PredicateBuilder, but the extension functions used are here in there completeness:
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T> () { return f => true; }
public static Expression<Func<T, bool>> False<T> () { return f => false; }
public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
}
Something like following - define operation classes to represent binary operation and build your tree:
interface IFilter
{
bool Filter(Record r);
}
class SimpleFilter : IFilter
{
bool Filter(Record r)
{
return RegExpMatch(r);
}
}
class AndFilter : IFilter
{
public AndFilter(IFilter left, IFilter right) {}
bool Filter(Record r)
{
return left.Filter(r) && right.Filter(r);
}
}
class OrFilter : IFilter
{
public OrFilter(IFilter left, IFilter right) {}
bool Filter(Record r)
{
return left.Filter(r) || right.Filter(r);
}
}
First step is to parse your expression into an abstract syntax tree. To do that, you can use the shunting-yard algorithm.
After you have done that, you can recursively evaluate the tree, using virtual methods or an interface. For example, you can have a SimpleNode class, that represents a simple expression (like 1 in your example) and can evaluate it. Then you have AndNode that represents AND operation and has two child nodes. It evaluates the child nodes and returns whether both succeeded.
This explanation of the Specification pattern (with example code) should help.
http://en.wikipedia.org/wiki/Specification_pattern#C.23
There may be libraries to do this sort of thing for you, but in the past, I've hand-rolled something along these lines, based around using Predicate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
public enum CombineOptions
{
And,
Or,
}
public class FilterExpression
{
public string Filter { get; set; }
public CombineOptions Options { get; private set; }
public FilterExpression(string filter, CombineOptions options)
{
this.Filter = filter;
this.Options = options;
}
}
public static class PredicateExtensions
{
public static Predicate<T> And<T>
(this Predicate<T> original, Predicate<T> newPredicate)
{
return t => original(t) && newPredicate(t);
}
public static Predicate<T> Or<T>
(this Predicate<T> original, Predicate<T> newPredicate)
{
return t => original(t) || newPredicate(t);
}
}
public static class ExpressionBuilder
{
public static Predicate<string> BuildExpression(IEnumerable<FilterExpression> filterExpressions)
{
Predicate<string> predicate = (delegate
{
return true;
});
foreach (FilterExpression expression in filterExpressions)
{
string nextFilter = expression.Filter;
Predicate<string> nextPredicate = (o => Regex.Match(o, nextFilter).Success);
switch (expression.Options)
{
case CombineOptions.And:
predicate = predicate.And(nextPredicate);
break;
case CombineOptions.Or:
predicate = predicate.Or(nextPredicate);
break;
}
}
return predicate;
}
}
class Program
{
static void Main(string[] args)
{
FilterExpression f1 = new FilterExpression(#"data([A-Za-z0-9\-]+)$", CombineOptions.And);
FilterExpression f2 = new FilterExpression(#"otherdata([A-Za-z0-9\-]+)$", CombineOptions.And);
FilterExpression f3 = new FilterExpression(#"otherdata([A-Za-z0-9\-]+)$", CombineOptions.Or);
// result will be false as "data1" does not match both filters
Predicate<string> pred2 = ExpressionBuilder.BuildExpression(new[] { f1, f2 });
bool result = pred2.Invoke("data1");
// result will be true as "data1" matches 1 of the 2 Or'd filters
Predicate<string> pred3 = ExpressionBuilder.BuildExpression(new[] { f1, f3 });
result = pred3.Invoke("data1");
}
}
}
All you'll need to do now is parse the 'brackets' to determine the order in which your FilterExpressions should be sent to the BuildExpression method. You might need to tweak it for more complex expressions, but hopefully this helps.

How to use the IEqualityComparer

I have some bells in my database with the same number. I want to get all of them without duplication. I created a compare class to do this work, but the execution of the function causes a big delay from the function without distinct, from 0.6 sec to 3.2 sec!
Am I doing it right or do I have to use another method?
reg.AddRange(
(from a in this.dataContext.reglements
join b in this.dataContext.Clients on a.Id_client equals b.Id
where a.date_v <= datefin && a.date_v >= datedeb
where a.Id_client == b.Id
orderby a.date_v descending
select new Class_reglement
{
nom = b.Nom,
code = b.code,
Numf = a.Numf,
})
.AsEnumerable()
.Distinct(new Compare())
.ToList());
class Compare : IEqualityComparer<Class_reglement>
{
public bool Equals(Class_reglement x, Class_reglement y)
{
if (x.Numf == y.Numf)
{
return true;
}
else { return false; }
}
public int GetHashCode(Class_reglement codeh)
{
return 0;
}
}
Your GetHashCode implementation always returns the same value. Distinct relies on a good hash function to work efficiently because it internally builds a hash table.
When implementing interfaces of classes it is important to read the documentation, to know which contract you’re supposed to implement.1
In your code, the solution is to forward GetHashCode to Class_reglement.Numf.GetHashCode and implement it appropriately there.
Apart from that, your Equals method is full of unnecessary code. It could be rewritten as follows (same semantics, ¼ of the code, more readable):
public bool Equals(Class_reglement x, Class_reglement y)
{
return x.Numf == y.Numf;
}
Lastly, the ToList call is unnecessary and time-consuming: AddRange accepts any IEnumerable so conversion to a List isn’t required. AsEnumerable is also redundant here since processing the result in AddRange will cause this anyway.
1 Writing code without knowing what it actually does is called cargo cult programming. It’s a surprisingly widespread practice. It fundamentally doesn’t work.
Try This code:
public class GenericCompare<T> : IEqualityComparer<T> where T : class
{
private Func<T, object> _expr { get; set; }
public GenericCompare(Func<T, object> expr)
{
this._expr = expr;
}
public bool Equals(T x, T y)
{
var first = _expr.Invoke(x);
var sec = _expr.Invoke(y);
if (first != null && first.Equals(sec))
return true;
else
return false;
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
}
Example of its use would be
collection = collection
.Except(ExistedDataEles, new GenericCompare<DataEle>(x=>x.Id))
.ToList();
If you want a generic solution that creates an IEqualityComparer for your class based on a property (which acts as a key) of that class have a look at this:
public class KeyBasedEqualityComparer<T, TKey> : IEqualityComparer<T>
{
private readonly Func<T, TKey> _keyGetter;
public KeyBasedEqualityComparer(Func<T, TKey> keyGetter)
{
if (default(T) == null)
{
_keyGetter = (x) => x == null ? default : keyGetter(x);
}
else
{
_keyGetter = keyGetter;
}
}
public bool Equals(T x, T y)
{
return EqualityComparer<TKey>.Default.Equals(_keyGetter(x), _keyGetter(y));
}
public int GetHashCode(T obj)
{
TKey key = _keyGetter(obj);
return key == null ? 0 : key.GetHashCode();
}
}
public static class KeyBasedEqualityComparer<T>
{
public static KeyBasedEqualityComparer<T, TKey> Create<TKey>(Func<T, TKey> keyGetter)
{
return new KeyBasedEqualityComparer<T, TKey>(keyGetter);
}
}
For better performance with structs there isn't any boxing.
Usage is like this:
IEqualityComparer<Class_reglement> equalityComparer =
KeyBasedEqualityComparer<Class_reglement>.Create(x => x.Numf);
Just code, with implementation of GetHashCode and NULL validation:
public class Class_reglementComparer : IEqualityComparer<Class_reglement>
{
public bool Equals(Class_reglement x, Class_reglement y)
{
if (x is null || y is null))
return false;
return x.Numf == y.Numf;
}
public int GetHashCode(Class_reglement product)
{
//Check whether the object is null
if (product is null) return 0;
//Get hash code for the Numf field if it is not null.
int hashNumf = product.hashNumf == null ? 0 : product.hashNumf.GetHashCode();
return hashNumf;
}
}
Example:
list of Class_reglement distinct by Numf
List<Class_reglement> items = items.Distinct(new Class_reglementComparer());
The purpose of this answer is to improve on previous answers by:
making the lambda expression optional in the constructor so that full object equality can be checked by default, not just on one of the properties.
operating on different types of classes, even complex types including sub-objects or nested lists. And not only on simple classes comprising only primitive type properties.
Not taking into account possible list container differences.
Here, you'll find a first simple code sample that works only on simple types (the ones composed only by primitif properties), and a second one that is complete (for a wider range of classes and complex types).
Here is my 2 pennies try:
public class GenericEqualityComparer<T> : IEqualityComparer<T> where T : class
{
private Func<T, object> _expr { get; set; }
public GenericEqualityComparer() => _expr = null;
public GenericEqualityComparer(Func<T, object> expr) => _expr = expr;
public bool Equals(T x, T y)
{
var first = _expr?.Invoke(x) ?? x;
var sec = _expr?.Invoke(y) ?? y;
if (first == null && sec == null)
return true;
if (first != null && first.Equals(sec))
return true;
var typeProperties = typeof(T).GetProperties();
foreach (var prop in typeProperties)
{
var firstPropVal = prop.GetValue(first, null);
var secPropVal = prop.GetValue(sec, null);
if (firstPropVal != null && !firstPropVal.Equals(secPropVal))
return false;
}
return true;
}
public int GetHashCode(T obj) =>
_expr?.Invoke(obj).GetHashCode() ?? obj.GetHashCode();
}
I know we can still optimize it (and maybe use a recursive?)..
But that is working like a charm without this much complexity and on a wide range of classes. ;)
Edit: After a day, here is my $10 attempt:
First, in a separate static extension class, you'll need:
public static class CollectionExtensions
{
public static bool HasSameLengthThan<T>(this IEnumerable<T> list, IEnumerable<T> expected)
{
if (list.IsNullOrEmptyCollection() && expected.IsNullOrEmptyCollection())
return true;
if ((list.IsNullOrEmptyCollection() && !expected.IsNullOrEmptyCollection()) || (!list.IsNullOrEmptyCollection() && expected.IsNullOrEmptyCollection()))
return false;
return list.Count() == expected.Count();
}
/// <summary>
/// Used to find out if a collection is empty or if it contains no elements.
/// </summary>
/// <typeparam name="T">Type of the collection's items.</typeparam>
/// <param name="list">Collection of items to test.</param>
/// <returns><c>true</c> if the collection is <c>null</c> or empty (without items), <c>false</c> otherwise.</returns>
public static bool IsNullOrEmptyCollection<T>(this IEnumerable<T> list) => list == null || !list.Any();
}
Then, here is the updated class that works on a wider range of classes:
public class GenericComparer<T> : IEqualityComparer<T> where T : class
{
private Func<T, object> _expr { get; set; }
public GenericComparer() => _expr = null;
public GenericComparer(Func<T, object> expr) => _expr = expr;
public bool Equals(T x, T y)
{
var first = _expr?.Invoke(x) ?? x;
var sec = _expr?.Invoke(y) ?? y;
if (ObjEquals(first, sec))
return true;
var typeProperties = typeof(T).GetProperties();
foreach (var prop in typeProperties)
{
var firstPropVal = prop.GetValue(first, null);
var secPropVal = prop.GetValue(sec, null);
if (!ObjEquals(firstPropVal, secPropVal))
{
var propType = prop.PropertyType;
if (IsEnumerableType(propType) && firstPropVal is IEnumerable && !ArrayEquals(firstPropVal, secPropVal))
return false;
if (propType.IsClass)
{
if (!DeepEqualsFromObj(firstPropVal, secPropVal, propType))
return false;
if (!DeepObjEquals(firstPropVal, secPropVal))
return false;
}
}
}
return true;
}
public int GetHashCode(T obj) =>
_expr?.Invoke(obj).GetHashCode() ?? obj.GetHashCode();
#region Private Helpers
private bool DeepObjEquals(object x, object y) =>
new GenericComparer<object>().Equals(x, y);
private bool DeepEquals<U>(U x, U y) where U : class =>
new GenericComparer<U>().Equals(x, y);
private bool DeepEqualsFromObj(object x, object y, Type type)
{
dynamic a = Convert.ChangeType(x, type);
dynamic b = Convert.ChangeType(y, type);
return DeepEquals(a, b);
}
private bool IsEnumerableType(Type type) =>
type.GetInterface(nameof(IEnumerable)) != null;
private bool ObjEquals(object x, object y)
{
if (x == null && y == null) return true;
return x != null && x.Equals(y);
}
private bool ArrayEquals(object x, object y)
{
var firstList = new List<object>((IEnumerable<object>)x);
var secList = new List<object>((IEnumerable<object>)y);
if (!firstList.HasSameLengthThan(secList))
return false;
var elementType = firstList?.FirstOrDefault()?.GetType();
int cpt = 0;
foreach (var e in firstList)
{
if (!DeepEqualsFromObj(e, secList[cpt++], elementType))
return false;
}
return true;
}
#endregion Private Helpers
We can still optimize it but it worth give it a try ^^.
The inclusion of your comparison class (or more specifically the AsEnumerable call you needed to use to get it to work) meant that the sorting logic went from being based on the database server to being on the database client (your application). This meant that your client now needs to retrieve and then process a larger number of records, which will always be less efficient that performing the lookup on the database where the approprate indexes can be used.
You should try to develop a where clause that satisfies your requirements instead, see Using an IEqualityComparer with a LINQ to Entities Except clause for more details.
IEquatable<T> can be a much easier way to do this with modern frameworks.
You get a nice simple bool Equals(T other) function and there's no messing around with casting or creating a separate class.
public class Person : IEquatable<Person>
{
public Person(string name, string hometown)
{
this.Name = name;
this.Hometown = hometown;
}
public string Name { get; set; }
public string Hometown { get; set; }
// can't get much simpler than this!
public bool Equals(Person other)
{
return this.Name == other.Name && this.Hometown == other.Hometown;
}
public override int GetHashCode()
{
return Name.GetHashCode(); // see other links for hashcode guidance
}
}
Note you DO have to implement GetHashCode if using this in a dictionary or with something like Distinct.
PS. I don't think any custom Equals methods work with entity framework directly on the database side (I think you know this because you do AsEnumerable) but this is a much simpler method to do a simple Equals for the general case.
If things don't seem to be working (such as duplicate key errors when doing ToDictionary) put a breakpoint inside Equals to make sure it's being hit and make sure you have GetHashCode defined (with override keyword).

Use a delegate for the equality comparer for LINQ's Distinct()

I have a LINQ Distinct() statement that uses my own custom comparer, like this:
class MyComparer<T> : IEqualityComparer<T> where T : MyType
{
public bool Equals(T x, T y)
{
return x.Id.Equals(y.Id);
}
public int GetHashCode(T obj)
{
return obj.Id.GetHashCode();
}
}
...
var distincts = bundle.GetAllThings.Distinct(new MyComparer<MySubType>());
This is all fine and dandy and works as I want. Out of curiosity, do I need to define my own Comparer, or can I replace it with a delegate? I thought I should be able to do something like this:
var distincts = bundle.GetAllThings.Distinct((a,b) => a.Id == b.Id);
But this doesn't compile. Is there a neat trick?
Distinct takes an IEqualityComparer as the second argument, so you will need an IEqualityComparer. It's not too hard to make a generic one that will take a delegate, though. Of course, this has probably already been implemented in some places, such as MoreLINQ suggested in one of the other answers.
You could implement it something like this:
public static class Compare
{
public static IEnumerable<T> DistinctBy<T, TIdentity>(this IEnumerable<T> source, Func<T, TIdentity> identitySelector)
{
return source.Distinct(Compare.By(identitySelector));
}
public static IEqualityComparer<TSource> By<TSource, TIdentity>(Func<TSource, TIdentity> identitySelector)
{
return new DelegateComparer<TSource, TIdentity>(identitySelector);
}
private class DelegateComparer<T, TIdentity> : IEqualityComparer<T>
{
private readonly Func<T, TIdentity> identitySelector;
public DelegateComparer(Func<T, TIdentity> identitySelector)
{
this.identitySelector = identitySelector;
}
public bool Equals(T x, T y)
{
return Equals(identitySelector(x), identitySelector(y));
}
public int GetHashCode(T obj)
{
return identitySelector(obj).GetHashCode();
}
}
}
Which gives you the syntax:
source.DistinctBy(a => a.Id);
Or, if you feel it's clearer this way:
source.Distinct(Compare.By(a => a.Id));
It's unfortunate that Distinct doesn't come up with such an overload, so what you have is a good option.
With MoreLinq, you can use the DistinctBy operator.
var distincts = bundle.GetAllThings.DistinctBy(a => a.Id);
You might also want to consider writing a generic ProjectionEqualityComparer that can turn the appropriate delegate into an IEqualityComparer<T> implementation, such as the one listed here.
Here is my perverse dirty little vanilla C# trick:
entities
.GroupBy(e => e.Id)
.Select(g => g.First())
This link shows how to create the extension method to be able to use Distinct in the manner you gave. You'll need to write two Distinct extension methods, and one IEqualityComparer.
Here's the code, from the site:
public static class Extensions
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer)
{
return source.Distinct(new DelegateComparer<T>(comparer));
}
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer, Func<T,int> hashMethod)
{
return source.Distinct(new DelegateComparer<T>(comparer,hashMethod));
}
}
public class DelegateComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> _equals;
private Func<T,int> _getHashCode;
public DelegateComparer(Func<T, T, bool> equals)
{
this._equals = equals;
}
public DelegateComparer(Func<T, T, bool> equals, Func<T,int> getHashCode)
{
this._equals = equals;
this._getHashCode = getHashCode;
}
public bool Equals(T a, T b)
{
return _equals(a, b);
}
public int GetHashCode(T a)
{
if (_getHashCode != null)
return _getHashCode(a);
else
return a.GetHashCode();
}
}
As of NET6, a DistinctBy extension method was added to the library in System.Linq.
example:
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune,
Planet.Pluto
};
foreach (Planet planet in planets.DistinctBy(p => p.Type))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }

How to get the index of an element in an IEnumerable?

I wrote this:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj
.Select((a, i) => (a.Equals(value)) ? i : -1)
.Max();
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value
, IEqualityComparer<T> comparer)
{
return obj
.Select((a, i) => (comparer.Equals(a, value)) ? i : -1)
.Max();
}
}
But I don't know if it already exists, does it?
I'd question the wisdom, but perhaps:
source.TakeWhile(x => x != value).Count();
(using EqualityComparer<T>.Default to emulate != if needed) - but you need to watch to return -1 if not found... so perhaps just do it the long way
public static int IndexOf<T>(this IEnumerable<T> source, T value)
{
int index = 0;
var comparer = EqualityComparer<T>.Default; // or pass in as a parameter
foreach (T item in source)
{
if (comparer.Equals(item, value)) return index;
index++;
}
return -1;
}
The whole point of getting things out as IEnumerable is so you can lazily iterate over the contents. As such, there isn't really a concept of an index. What you are doing really doesn't make a lot of sense for an IEnumerable. If you need something that supports access by index, put it in an actual list or collection.
I would implement it like this:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj.IndexOf(value, null);
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value, IEqualityComparer<T> comparer)
{
comparer = comparer ?? EqualityComparer<T>.Default;
var found = obj
.Select((a, i) => new { a, i })
.FirstOrDefault(x => comparer.Equals(x.a, value));
return found == null ? -1 : found.i;
}
}
The way I'm currently doing this is a bit shorter than those already suggested and as far as I can tell gives the desired result:
var index = haystack.ToList().IndexOf(needle);
It's a bit clunky, but it does the job and is fairly concise.
I think the best option is to implement like this:
public static int IndexOf<T>(this IEnumerable<T> enumerable, T element, IEqualityComparer<T> comparer = null)
{
int i = 0;
comparer = comparer ?? EqualityComparer<T>.Default;
foreach (var currentElement in enumerable)
{
if (comparer.Equals(currentElement, element))
{
return i;
}
i++;
}
return -1;
}
It will also not create the anonymous object
The best way to catch the position is by FindIndex This function is available only for List<>
Example
int id = listMyObject.FindIndex(x => x.Id == 15);
If you have enumerator or array use this way
int id = myEnumerator.ToList().FindIndex(x => x.Id == 15);
or
int id = myArray.ToList().FindIndex(x => x.Id == 15);
A bit late in the game, i know... but this is what i recently did. It is slightly different than yours, but allows the programmer to dictate what the equality operation needs to be (predicate). Which i find very useful when dealing with different types, since i then have a generic way of doing it regardless of object type and <T> built in equality operator.
It also has a very very small memory footprint, and is very, very fast/efficient... if you care about that.
At worse, you'll just add this to your list of extensions.
Anyway... here it is.
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int retval = -1;
var enumerator = source.GetEnumerator();
while (enumerator.MoveNext())
{
retval += 1;
if (predicate(enumerator.Current))
{
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
return retval;
}
}
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
return -1;
}
Hopefully this helps someone.
A few years later, but this uses Linq, returns -1 if not found, doesn't create extra objects, and should short-circuit when found [as opposed to iterating over the entire IEnumerable]:
public static int IndexOf<T>(this IEnumerable<T> list, T item)
{
return list.Select((x, index) => EqualityComparer<T>.Default.Equals(item, x)
? index
: -1)
.FirstOr(x => x != -1, -1);
}
Where 'FirstOr' is:
public static T FirstOr<T>(this IEnumerable<T> source, T alternate)
{
return source.DefaultIfEmpty(alternate)
.First();
}
public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, T alternate)
{
return source.Where(predicate)
.FirstOr(alternate);
}
Stumbled across this today in a search for answers and I thought I'd add my version to the list (No pun intended). It utlises the null conditional operator of c#6.0
IEnumerable<Item> collection = GetTheCollection();
var index = collection
.Select((item,idx) => new { Item = item, Index = idx })
//or .FirstOrDefault(_ => _.Item.Prop == something)
.FirstOrDefault(_ => _.Item == itemToFind)?.Index ?? -1;
I've done some 'racing of the old horses' (testing) and for large collections (~100,000), worst case scenario that item you want is at the end, this is 2x faster than doing ToList().FindIndex(). If the Item you want is in the middle its ~4x faster.
For smaller collections (~10,000) it seems to be only marginally faster
Heres how I tested it https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e
An alternative to finding the index after the fact is to wrap the Enumerable, somewhat similar to using the Linq GroupBy() method.
public static class IndexedEnumerable
{
public static IndexedEnumerable<T> ToIndexed<T>(this IEnumerable<T> items)
{
return IndexedEnumerable<T>.Create(items);
}
}
public class IndexedEnumerable<T> : IEnumerable<IndexedEnumerable<T>.IndexedItem>
{
private readonly IEnumerable<IndexedItem> _items;
public IndexedEnumerable(IEnumerable<IndexedItem> items)
{
_items = items;
}
public class IndexedItem
{
public IndexedItem(int index, T value)
{
Index = index;
Value = value;
}
public T Value { get; private set; }
public int Index { get; private set; }
}
public static IndexedEnumerable<T> Create(IEnumerable<T> items)
{
return new IndexedEnumerable<T>(items.Select((item, index) => new IndexedItem(index, item)));
}
public IEnumerator<IndexedItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Which gives a use case of:
var items = new[] {1, 2, 3};
var indexedItems = items.ToIndexed();
foreach (var item in indexedItems)
{
Console.WriteLine("items[{0}] = {1}", item.Index, item.Value);
}
This can get really cool with an extension (functioning as a proxy), for example:
collection.SelectWithIndex();
// vs.
collection.Select((item, index) => item);
Which will automagically assign indexes to the collection accessible via this Index property.
Interface:
public interface IIndexable
{
int Index { get; set; }
}
Custom extension (probably most useful for working with EF and DbContext):
public static class EnumerableXtensions
{
public static IEnumerable<TModel> SelectWithIndex<TModel>(
this IEnumerable<TModel> collection) where TModel : class, IIndexable
{
return collection.Select((item, index) =>
{
item.Index = index;
return item;
});
}
}
public class SomeModelDTO : IIndexable
{
public Guid Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Index { get; set; }
}
// In a method
var items = from a in db.SomeTable
where a.Id == someValue
select new SomeModelDTO
{
Id = a.Id,
Name = a.Name,
Price = a.Price
};
return items.SelectWithIndex()
.OrderBy(m => m.Name)
.Skip(pageStart)
.Take(pageSize)
.ToList();
Try this:
static int FindIndex<T>(this IEnumerable<T> a, Predicate<T> f) =>
a.TakeWhile(x => !f(x)).Count();
static int IndexOf<T>(this IEnumerable<T> a, T value) =>
a.FindIndex(x => EqualityComparer<T>.Default.Equals(x, value));
var i = new[] { 1, 2, 3 }.IndexOf(2); // 1

Categories