问题
I have a Sequence
type that implements ISequence
. ISequence
implements IEnumerable<Element>
where Element
is another custom type. Currently, my Sequence
type stores the instructions for generating the N-th term of a sequence as a Func<int, int>
. This is convenient because it allows me to call NTerm(int n)
with a simple call to the Func
and to create Sequence
s with a lambda. I would like to avoid changing that approach.
I would like to check equality of two Sequence objects based on equality of the two Func
s. I began browsing around, and there are a few posts that use Expression
s to break down lambdas and Func
s for equality, but I'm talking about mathematical equality.
In other words,
x => 2 * x
should equalc => c * 2
, along with any variations of mathematical expressions, such as Math.Pow or more involved operators. If I can get that to work, I can compareSequence
s for mathematical equality.
I tried to write my own extension method:
public static bool MathEquals(this Expression<Func<int, int>> f,
Expression<Func<int, int>> g)
I'm not sure how to go from there. I have some basic defaults written:
if (ReferenceEquals (f, g)) return true;
if (f == null || g == null) return false;
if (f.NodeType != g.NodeType || f.Type != g.Type) return false;
but I need to check the mathematical equality of the two lambda expressions, i.e. the two Func<int, int>
s. Can this be done? Does anyone have a solution? Do I need to change my approach for storing the N-th term formula? I'm against checking the output because sequences can be equal for some output and not all.
If I need to post any of the Sequence code, I will.
UPDATE: I've decided to mark Scott's answer as accepted. However, the work is not complete. Check out part two here.
回答1:
There are two parts to your question, "How do I break apart a expression and evaulate it", and "How do I check that two expressions mean the same logical operation".
I don't know how to do the 2nd part, but I do know the first.
What you will need to do is create a ExpressionVisitor and have it walk through each BinaryExpression by overriding VisitBinary
and building up a list of all operations.
public class OperationParser : ExpressionVisitor
{
public OperationParser()
{
Expressions = new List<BinaryExpression>();
}
public List<BinaryExpression> Expressions { get; private set; }
protected override Expression VisitBinary(BinaryExpression b)
{
Expressions.Add(b);
return base.VisitBinary(b);
}
}
Then you would do
Expression<Func<int, int>> expression1 = (x) => x + 2;
Expression<Func<int, int>> expression2 = (y) => 2 + y;
var parser1 = new OperationParser();
parser1.Visit(expression1);
var parser2 = new OperationParser();
parser2.Visit(expression2);
//TODO: write a way to compare parser1.Expressions to parser2.Expressions to see if they "mean the same thig"
You just need to fill in the TODO with "your second question"
来源:https://stackoverflow.com/questions/31643934/mathematical-equality-for-funcint-int