所以我正在使用C#4开发一些适用于dynamic
变量的东西。而且我的情况是我有两个变量a
和b
而我知道已定义a.Foo(b)
或b.Foo(a)
。但是我不知道现在我使用的是什么:
dynamic a, b, result;
...
try
{
result = a.Foo(b);
}
catch
{
result = b.Foo(a);
}
哪个是可怕的(不仅是它不优雅,而且非常慢,因为提升Exception
并产生堆栈跟踪的概率大约为0.5)。我可以使用反射,但我希望它也会很慢。
那么有更好的方法吗?
所以这就是问题......但我也会解释上下文,因为我认为有一个更好的方法来处理整个情况。基本上我正在构建表达式树(使用我自己的节点结构),它可以处理许多不同的数据类型。
如果您考虑表达式1+'2'
,则a
和b
值是操作数1
和'2'
。如果我想评估具有子树+
和a
的{{1}}节点,则任一操作数可能包含一个方法b
另一个操作数的类型。也就是说,Add
已实施或a.Add(b)
已实施。
我只能考虑使用反射,上面的方法,或者在b.Add(a)
和a
这两种类型中生成重复函数来模拟对称性。
答案 0 :(得分:1)
Microsoft建议您通过提供IsImplemented
属性或方法来执行此操作,在调用其中一个对象之前,您应该可以调用它来确定哪些对象实现Foo
,但只能查找它没有。
异常处理的开销不是巨大的,但它很明显,除非你正在处理异常情况,否则你应该真的避免异常。这是来自C / C ++的异常和错误代码之间的主要区别。
所以,添加一个IsFooImplemented
属性或类似的东西。它会为你节省一个例外。
答案 1 :(得分:0)
如果要将两个操作数转换为正确的数字,然后再尝试添加它们呢?
即,使用如here所述的System.Convert
,然后:
dynamic a2 = DoConvertToInteger(a);
dynamic b2 = DoConvertToInteger(b);
result = a2 + b2;
答案 2 :(得分:0)
我认为(就像Ed所说)我会通过使用一个接口(即IResolve)解决这个问题,该接口应用于层次结构中的每个节点:
Interface IResolve {
IResolve Resolve();
object Value { get; }
bool IsResolved { get; }
}
class Add : IResolve {
List<IResolve> entities;
protected IResolve doMyAddLogic(IResolve lvalue, IResolve rvalue) {
return new ResolvedNodeValue(lvalue.Value + rvalue.Value);
}
public IResolve Resolve() {
IResolve result = null;
foreach(var child in entities) {
result = doMyAddLogic(result, child.Resolve());
}
return result;
}
}
问题在于您对界面背后的分辨率存在歧义。它不完美,我不喜欢缺乏正式的语言符号(即树的确定性),但它可能是一个开始的地方。