开发者

Restructuring to not use Exceptions by Determining which Method is Implemented

开发者 https://www.devze.com 2022-12-16 00:49 出处:网络
So I\'m developing something that works on dynamic variables using C# 4. And I\'m in a situation where I have two variables a and b a开发者_运维百科nd I know that either a.Foo(b) or b.Foo(a) is define

So I'm developing something that works on dynamic variables using C# 4. And I'm in a situation where I have two variables a and b a开发者_运维百科nd I know that either a.Foo(b) or b.Foo(a) is defined. However I don't know which so at the moment I use something like this:

dynamic a, b, result;
...

try
{
    result = a.Foo(b);
}
catch
{
    result = b.Foo(a);
}

Which is horrible (not only is it inelegant but it's very slow since there is around a 0.5 probability of raising an Exception and producing a stack trace). I could use reflection but I expect that'd be quite slow too.

So is there a better way?


So that's the problem... but I'll also explain the context since I think there's a good chance there's a better way to handle the whole situation. Essentially I am building expression trees (using my own node structure) that work with many different datatypes.

If you consider the expression 1+'2', the a and b values are the operands 1 and '2'. If I want to evaluate the + node, which has the sub-trees a and b, then either operand may contain a method to Add the other operand's type to it. That is, either a.Add(b) is implemented or b.Add(a) is implemented.

I can only think of using reflection, the method above, or producing duplicate functions in both types of a and b to model the symmetry.


Microsoft would recommend that you do it by providing an IsImplemented property or method, which you should be able to call to determine which of your objects implements Foo before calling one of them, only to find that it doesn't.

The overhead of exception handling isn't huge, but it is noticeable, and you should really avoid exceptions unless you're handling an exceptional scenario. This is a major difference between exceptions and error codes from C/C++.

So, add an IsFooImplemented property or something like that. It'll save you an exception.


I think (like Ed said) I would resolve this by using a Interface (i.e. IResolve), which is applied to each of the nodes in your hierarchy:

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

The problem is that you will have ambiguity with the resolution being behind an Interface. Its not perfect, and I dont like the lack of formal language notation (i.e. determinism of the tree), but it might be a place to start.


How about converting both operands to a proper number before trying to add them?

I.e., use something like System.Convert as described here, then:

dynamic a2 = DoConvertToInteger(a);
dynamic b2 = DoConvertToInteger(b);

result = a2 + b2;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号