C# C语言中的表达式树和惰性求值#

C# C语言中的表达式树和惰性求值#,c#,lazy-evaluation,expression-trees,C#,Lazy Evaluation,Expression Trees,我有一小段代码,其中我获取字符串数组ParameterExpression并将特定索引转换为目标类型。我可以通过调用Parse(如果类型为基元)或尝试原始转换(希望转换为字符串或隐式字符串)来实现这一点 这是可行的,但我正试图重写条件语句 paramValue = Expression.Condition( Expression.Constant(paramType.IsPrimitive), Expression.Call(parseMethod, paramValue),

我有一小段代码,其中我获取字符串数组
ParameterExpression
并将特定索引转换为目标类型。我可以通过调用
Parse
(如果类型为基元)或尝试原始转换(希望转换为字符串或隐式字符串)来实现这一点

这是可行的,但我正试图重写条件语句

paramValue = Expression.Condition(
    Expression.Constant(paramType.IsPrimitive),
    Expression.Call(parseMethod, paramValue),
    Expression.Convert(paramValue, paramType)
);
这总是导致
System.InvalidOperationException
,可能是因为它尝试两种转换。我发现第二种风格更直观,所以这是不幸的


我是否可以将求值延迟到实际需要值时进行编写?

表达式将代码表示为数据,此处不求值true和false分支;它不是“尝试两种转换”。相反,它试图构建一个表示每个转换的表达式树。然而,条件作为一个
常量
,正在根据类型被急切地烘焙到条件中

您正在构建具有以下结构的表达式:

var result = true // <`true` or `false` based on the type T> 
    ? T.Parse(val)
    : (T) val;
即使它只会执行显式cast操作符,因为
Foo
不是原语

您的原始代码实际上已经构建了一个表达式,该表达式将使用基于
T
的“正确”转换策略,而无需编译/计算另一个表达式。如果这对您不起作用,我怀疑这是因为所涉及的类型没有从
string
定义显式强制转换


顺便说一句,我不鼓励将
paramValue
作为原始(未转换)值和转换值进行重用,这会使调试变得比需要的困难得多,尤其是。。。在新闻业中有:谁、什么、在哪里、何时、为什么(加上如何)。。在编程方面也是如此。谁抛出异常(这是什么)?让我们使代码更易于调试:

static Expression ParseOrConvert(ParameterExpression strArray, ConstantExpression index, ParameterInfo paramInfo)
{
    Type paramType = paramInfo.ParameterType;

    Expression paramValue = Expression.ArrayIndex(strArray, index);
    MethodInfo parseMethod = paramType.GetMethod("Parse", new[] { typeof(string) });

    var isPrimitive = Expression.Constant(paramType.IsPrimitive);
    var call = Expression.Call(parseMethod, paramValue);
    var convert = Expression.Convert(paramValue, paramType);

    var paramValue2 = Expression.Condition(
        isPrimitive,
        call,
        convert
    );

    return paramValue2;
}
然后像这样称呼它:

public static void MyMethod(int par1)
{
}
然后

ParameterExpression strArray = Expression.Parameter(typeof(string[]));

// paramType int
var paramInfo = typeof(Program).GetMethod("MyMethod").GetParameters()[0];

var result = ParseOrConvert(strArray, Expression.Constant(0), paramInfo);
现在。。。谁抛出异常
Expression.Convert(paramValue,paramType)
引发异常。。。为什么?因为您正在尝试执行以下操作:

string paramValue = ...;
convert = (int)paramValue;
那当然是违法的!即使是“死”代码(无法访问的代码)也必须在.NET(其IL语言)中“可编译”。因此,您的错误是试图在表达式中引入一些非法死代码,即:

string paramValue = ...;
isPrimitive = true ? int.Parse(paramValue) : (int)paramValue;

这不会用C#编译,甚至可能不能用IL代码编写。还有表达式类。什么是
paramType
paramValue
parseMethod
等等。未知数太多了。请在此处创建完整的上下文,尽管这不是我试图解决的具体问题,更像是一个一般性问题。您仍然需要提供一些示例代码,而这不是指向另一个问题的链接。使其更好:DSide注意-在这种特殊情况下更直观的是使用重载接受可选的
MethodInfo
,例如
paramValue=Expression.Convert(paramValue,paramType,paramType.IsPrimitive?paramType.GetMethod(“Parse”,new[]{typeof(string)}):null)
string paramValue = ...;
convert = (int)paramValue;
string paramValue = ...;
isPrimitive = true ? int.Parse(paramValue) : (int)paramValue;