2010-04-23 52 views
3

我有以下两个类,它们提供了彼此之间的一对一映射。我如何处理空值,当我运行第二个测试时,我得到了一个stackoverflow异常。我怎样才能停止这个递归循环?谢谢维护对象之间的一对一映射

[TestMethod] 
public void SetY() 
{ 
    var x = new X(); 
    var y = new Y(); 

    x.Y = y; 

    Assert.AreSame(x.Y, y); 
    Assert.AreSame(y.X, x); 
} 

[TestMethod] 
public void SetYToNull() 
{ 
    var x = new X(); 
    var y = new Y(); 

    x.Y = y; 
    y.X = null; 

    Assert.IsNull(x.Y); 
    Assert.IsNull(y.X); 
} 

public class X 
{ 
    private Y _y; 

    public Y Y 
    { 
     get { return _y; } 
     set 
     { 
      if(_y != value) 
      { 
       if(_y != null) 
       { 
        _y.X = null; 
       } 

       _y = value; 

       if(_y != null) 
       { 
        _y.X = this; 
       } 
      } 
     } 
    } 
} 

public class Y 
{ 
    private X _x; 

    public X X 
    { 
     get { return _x; } 
     set 
     { 
      if (_x != value) 
      { 
       if (_x != null) 
       { 
        _x.Y = null; 
       } 

       _x = value; 

       if (_x != null) 
       { 
        _x.Y = this; 
       } 
      } 
     } 
    } 
} 
+1

你想完成什么? – 2010-04-23 05:47:51

+0

当我将x.Y设置为null时,我希望x.Y和y.X都为null,因为它们都相互引用,基本上我想维护两个对象之间的双向引用 – 2010-04-23 06:11:39

+0

您可能想重新考虑此设计。 – 2010-04-23 06:15:35

回答

1

这工作正常:

public class ClassX 
{ 
    private ClassY _Y; 

    public ClassY Y 
    { 
     get { return _Y; } 
     set 
     { 
      if (_Y != value) 
      { 
       var oldY = _Y; 
       _Y = value; 

       if (_Y == null) 
       { 
        oldY.X = null; 
       } 
       else 
       { 
        _Y.X = this;  
       } 
      } 
     } 
    } 
} 

public class ClassY 
{ 
    private ClassX _X; 

    public ClassX X 
    { 
     get { return _X; } 
     set 
     { 
      if (_X != value) 
      { 
       var oldX = _X; 

       _X = value; 
       if (_X == null) 
       { 
        oldX.Y = null; 
       } 
       else 
       { 
        _X.Y = this;  
       } 

      } 
     } 
    } 
} 
0

你在这里遇到无限循环。

如果你只是不想让null S,使用此:

get 
{ 
    if (_y == null) 
     _y = new Y(); 
    return _y; 
} 
0

使用独立的实体来存储对象之间的关系。就像这样:

[TestFixture] 
    public class Tester 
    { 
     [Test] 
     public void SetY() 
     { 
      var refs = new References(); 

      var x = new X(refs); 
      var y = new Y(refs); 

      x.Y = y; 

      Assert.AreSame(x.Y, y); 
      Assert.AreSame(y.X, x); 
     } 

     [Test] 
     public void SetYToNull() 
     { 
      var refs = new References(); 

      var x = new X(refs); 
      var y = new Y(refs); 


      x.Y = y; 
      y.X = null; 

      Assert.IsNull(x.Y); 
      Assert.IsNull(y.X); 
     } 
    } 

    public class References 
    { 
     private IDictionary<X, Y> refs = new Dictionary<X, Y>(); 

     public bool Contains(X x, Y y) 
     { 
      if (!refs.ContainsKey(x)) return false; 
      if (refs[x] != y) return false; 

      return true; 
     } 

     public void Delete(X x) 
     { 
      refs.Remove(x); 
     } 

     public void Add(X x, Y y) 
     { 
      refs.Add(x, y); 
     } 

     public Y Get(X x) 
     { 
      return refs.ContainsKey(x) ? refs[x] : null; 
     } 

     public X Get(Y y) 
     { 
      var pairs = refs.Where(r => r.Value == y); 

      return pairs.Any() ? pairs.FirstOrDefault().Key : null; 
     } 

     public void Delete(Y y) 
     { 
      X x = Get(y); 

      if (x != null) 
      { 
       Delete(x); 
      } 
     } 
    } 

    public class X 
    { 
     private readonly References refs; 

     public X(References refs) 
     { 
      this.refs = refs; 
     } 

     public Y Y 
     { 
      get { return refs.Get(this); } 
      set 
      { 
       if (value == null) 
       { 
        refs.Delete(this); 
       } 
       else 
       { 
        if (!refs.Contains(this, value)) 
        { 
         refs.Add(this, value); 
        } 
       } 
      } 
     } 
    } 

    public class Y 
    { 
     private References refs; 

     public Y(References refs) 
     { 
      this.refs = refs; 
     } 

     public X X 
     { 
      get { return refs.Get(this); } 
      set 
      { 
       if (value == null) 
       { 
        refs.Delete(this); 
       } 
       else 
       { 
        if (!refs.Contains(value, this)) 
        { 
         refs.Add(value, this); 
        } 
       } 
      } 
     } 
    } 
1

当设置y.X = null;,什么情况是,它会尝试设置YX为_x空不为空,这反过来又试图设置( yX).Y为null,因为x中的_y仍然不为空,并且......你得到了这个想法 - 一个无限循环。

我已经改变了它,以便在分配给成员变量的属性之前先指定成员值。

public class X 
{ 
    private Y _y; 

    public Y Y 
    { 
     get { return _y; } 
     set 
     { 
      if (_y != value) 
      { 
       Y temp = _y; 

       _y = value; 

       // If new value is not null 
       if (_y != null) 
       { 
        _y.X = this; 
       } 
       // If old value is not null but new value is 
       else if (temp != null) 
       { 
        temp.X = null; 
       } 
      } 
     } 
    } 
} 

public class Y 
{ 
    private X _x; 

    public X X 
    { 
     get { return _x; } 
     set 
     { 
      if (_x != value) 
      { 
       X temp = _x; 

       _x = value; 

       // If new value is not null 
       if (_x != null) 
       { 
        _x.Y = this; 
       } 
       // If old value is not null but new value is 
       else if (temp != null) 
       { 
        temp.Y = null; 
       } 
      } 
     } 
    } 
} 
+0

你可以删除这个:'if(temp!= null)',因为在setter开始时你检查'_x!= value',如果新值是'null',temp变量总是不为null。看到我的答案。 – bniwredyc 2010-04-23 06:23:22

+0

你是对的!谢谢! – anonymous 2010-04-23 06:31:57