help
Root Question Message
Expression.Lambda<Func<...>>(...)
, you don't then need to cast the result of lambda.Compile()
Unsafe.As
?Unsafe.As
once for each field, rather than onceExpression.Convert
thereUnsafe.As
in a variableUnsafe.As
is illegal anyway Expression.Block
. var castParam1 = Expression.Variable(...);
...
var blockMembers = new Expression[]
{
Expression.Assign(castParam1, unsafeAs),
Expression.Assign(castParam2, unsafeAs),
comparisonsConjuncted,
};
var block = Expression.Block(new[] { castParam1, castParam2 }, blockMembers);
var lambda = Expression.Lambda<...>(block, new[] { param1, param2 });
castParam1
etc in comparisons
of course) private static AsmGetHashCodeDelegate CreateHashCodeFunc(Type asmType)
{
var getTypeMethod = asmType.GetMethod(nameof(GetType))!;
var toHashCodeMethod = typeof(HashCode).GetMethod(nameof(HashCode.ToHashCode))!;
var param = Expression.Parameter(typeof(IAsyncStateMachine));
var hashCode = Expression.Variable(typeof(HashCode));
var asmAsConcreteType = Expression.Variable(asmType);
var blockExprs = new List<Expression>();
blockExprs.Add(Expression.Assign(hashCode, Expression.Default(typeof(HashCode))));
blockExprs.Add(Expression.Assign(asmAsConcreteType, CastToConcreteType(param, asmType)));
foreach (var field in GetRelevantFields(asmType))
{
blockExprs.Add(Expression.Call(
instance: hashCode,
methodName: nameof(HashCode.Add),
typeArguments: new[] { field.FieldType },
arguments: Expression.MakeMemberAccess(asmAsConcreteType, field)));
}
blockExprs.Add(Expression.Call(
instance: hashCode,
method: toHashCodeMethod));
var block = Expression.Block(blockExprs);
var lambda = Expression.Lambda<Func<IAsyncStateMachine, int>>(block, param);
return new(lambda.Compile());
}
System.InvalidOperationException: 'variable '' of type 'System.HashCode' referenced from scope '', but it is not defined'
You need to give it the list of variables used in the block as well
Expression.Block(new[] { hashCode, asmAsConcreteType }, ...)