代码之家  ›  专栏  ›  技术社区  ›  zildjohn01

C#==或==中的类宏结构如何分解包含“return”的函数

  •  3
  • zildjohn01  · 技术社区  · 14 年前

    我发现自己在代码中一遍又一遍地重复以下模式,几十次甚至几百次:

    object Function() {
        this.Blah = this.Blah.Resolve(...);
        if(this.Blah == null)
            return null;
        if(this.Blah.SomeFlag)
            return this.OtherFunction();
    
        // otherwise, continue processing...
    }
    

    我想写这样的东西:

    object Function() {
        this.Blah = this.Blah.Resolve(...);
        VerifyResolve(this.Blah);
    
        // continue processing...
    }
    

    除了模式包含条件 return 意味着我不能算出一个函数。我已经有一次微妙地改变了模式,因为我不能做一个简单的搜索,所以很难找到所有的实例。

    我怎样才能避免不必要地重复我自己,并且使将来对这种模式的任何改变变得更容易呢?

    7 回复  |  直到 14 年前
        1
  •  1
  •   ChrisW    14 年前

    你可以这样说:

    object Function()
    { 
        this.Blah = this.Blah.Resolve(...);
        object rc;
        if (!VerifyResolve(out rc)
           return rc;
    
        // continue processing... 
    } 
    
    bool VerifyResolve(out object rc)
    {
        if(this.Blah == null)      
        {
            rc = null;
            return true;
        }
        if(this.Blah.SomeFlag)      
        {
            rc = this.OtherFunction();
            return true;
        }
        rc = null;
        return false;
    }
    
        2
  •  3
  •   Martin Liversage    14 年前

    如果你经常发现你必须检查 null Null Object Pattern . 实际上,您创建了一个表示空结果的对象。然后可以返回此对象而不是 无效的

    MyClass Function() 
    {  
      this.Blah = this.Blah.Resolve(...); 
      VerifyResolve(this.Blah);
    
      // continue processing...  
    }  
    
    MyClass VerifyResolve(MyClass rc) 
    {
      // ...
      return rc.Blah.SomeFlag ? rc.OtherFunction() : rc;
    } 
    
    NullMyClass : MyClass {
      public override bool SomeFlag { get { return false; } }
    }
    
        3
  •  1
  •   Yellowfog    14 年前

    if (!TryResolve(this.Blah)) return this.Blah;
    

    其中TryResolve将this.Blah的值设置为null或this.OtherFunction,并返回适当的bool

        4
  •  1
  •   Ed James    14 年前

    this.Blah = this.Blah.Resolve(...);
    

    我遇到的主要问题是对象返回类型和属性对通过调用该属性的方法返回的值的赋值。这两个系统闻起来都像是你在某个地方把继承搞砸了,最后得到了一个有状态的系统,这既是要测试的麻烦,也是要维护的痛苦。

    也许最好是重新思考,而不是试图使用黑客和技巧来回避这个问题:我通常会发现,如果我试图滥用语言的功能,如宏,那么我的设计需要工作!

    编辑

    好吧,补充一下信息,也许这不是什么味道,但我还是建议如下:

    class ExampleExpr{
        StatefulData data ... // some variables that contain the state data
        BladhyBlah Blah { get; set; }
    
        object Function(params) {
            this.Blah = this.Blah.Resolve(params);
            ....
        }
    }
    

    这段代码令人担忧,因为它强制采用完全基于状态的方法,输出取决于之前发生的事情,因此需要特定的步骤来复制。这是一个痛苦的考验。另外,如果调用Function()两次,如果不知道Blah最初处于什么状态,就无法保证它会发生什么。

    class ExampleExpr{
        StatefulData data ... // some variables that contain the state data
    
        object Function(params) {
            BlahdyBlah blah = BlahdyBlah.Resolve(params, statefulData);
        }
    }
    

    这意味着我们可以通过使用特定的Setup()调用函数(params)来复制测试中的任何功能,从而创建statefulData和一组特定的params。

    理论上,这效率较低(因为在每个工厂调用上都会创建一个新的BlahdyBlah),但是可以用特定的数据缓存BlahdyBlah实例,并在工厂调用之间共享它们(假设它们没有影响其内部状态的其他方法)。然而,它更易于维护,而且从测试的角度来看,它完全消除了有状态数据的麻烦。

    这也有助于消除最初的问题,因为当我们不依赖内部实例变量时,我们都可以从函数(params)外部解析(params,statefulData),如果blah==null或blah.SomeFlag==SomeFlag.Whatever,则不调用函数(params)。因此,通过将其移到方法之外,我们不再需要担心返回。

    希望这是正确的,举个小例子,很难确切地知道该推荐什么,因为这里通常有困难/抽象的问题。

        5
  •  0
  •   tsinik    14 年前

    如果您拥有Blah源代码,那么最好创建一些可解析的接口并让Blah实现它。

        6
  •  0
  •   Henrik    14 年前
    object Function() { 
        this.Blah = this.Blah.Resolve(...);
        object result;
        if (VerifyResolve(this.Blah, out result))
            return result;
    
        // continue processing... 
    } 
    
        7
  •  0
  •   ChrisW    14 年前

    这是混乱,恼人,冗长,但这是我不得不去的。可能没有更好的办法了。

    struct Rc
    {
      internal object object;
      internal Rc(object object) { this.object = object; }
    }
    
    object Function() 
    {  
        this.Blah = this.Blah.Resolve(...); 
        Rc? rc = VerifyResolve();
        if (rc.HasValue)
           return rc.Value.object; 
    
        // continue processing...  
    }  
    
    Rc? VerifyResolve() 
    { 
        if(this.Blah == null)       
        { 
            return new Rc(null); 
        } 
        if(this.Blah.SomeFlag)       
        { 
            return new Rc(this.OtherFunction()); 
        } 
        return null; 
    }