重构为不通过确定实施哪个方法来使用例外

时间:2010-01-06 00:36:39

标签: oop reflection dynamic c#-4.0

所以我正在使用C#4开发一些适用于dynamic变量的东西。而且我的情况是我有两个变量ab而我知道已定义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',则ab值是操作数1'2'。如果我想评估具有子树+a的{​​{1}}节点,则任一操作数可能包含一个方法b另一个操作数的类型。也就是说,Add已实施或a.Add(b)已实施。

我只能考虑使用反射,上面的方法,或者在b.Add(a)a这两种类型中生成重复函数来模拟对称性。

3 个答案:

答案 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;
   }
}

问题在于您对界面背后的分辨率存在歧义。它不完美,我不喜欢缺乏正式的语言符号(即树的确定性),但它可能是一个开始的地方。