Conversion AnonymousFunctionConversion(ResolveResult resolveResult, IType toType)
{
// C# 4.0 spec §6.5 Anonymous function conversions
LambdaResolveResult f = resolveResult as LambdaResolveResult;
if (f == null)
{
return(Conversion.None);
}
if (!f.IsAnonymousMethod)
{
// It's a lambda, so conversions to expression trees exist
// (even if the conversion leads to a compile-time error, e.g. for statement lambdas)
toType = UnpackExpressionTreeType(toType);
}
IMethod d = toType.GetDelegateInvokeMethod();
if (d == null)
{
return(Conversion.None);
}
IType[] dParamTypes = new IType[d.Parameters.Count];
for (int i = 0; i < dParamTypes.Length; i++)
{
dParamTypes[i] = d.Parameters[i].Type;
}
IType dReturnType = d.ReturnType;
if (f.HasParameterList)
{
// If F contains an anonymous-function-signature, then D and F have the same number of parameters.
if (d.Parameters.Count != f.Parameters.Count)
{
return(Conversion.None);
}
if (f.IsImplicitlyTyped)
{
// If F has an implicitly typed parameter list, D has no ref or out parameters.
foreach (IParameter p in d.Parameters)
{
if (p.IsOut || p.IsRef)
{
return(Conversion.None);
}
}
}
else
{
// If F has an explicitly typed parameter list, each parameter in D has the same type
// and modifiers as the corresponding parameter in F.
for (int i = 0; i < f.Parameters.Count; i++)
{
IParameter pD = d.Parameters[i];
IParameter pF = f.Parameters[i];
if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut)
{
return(Conversion.None);
}
if (!dParamTypes[i].Equals(pF.Type))
{
return(Conversion.None);
}
}
}
}
else
{
// If F does not contain an anonymous-function-signature, then D may have zero or more parameters of any
// type, as long as no parameter of D has the out parameter modifier.
foreach (IParameter p in d.Parameters)
{
if (p.IsOut)
{
return(Conversion.None);
}
}
}
return(f.IsValid(dParamTypes, dReturnType, this));
}