Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 维护对象之间的一对一映射_C# - Fatal编程技术网

C# 维护对象之间的一对一映射

C# 维护对象之间的一对一映射,c#,C#,我有以下两个类,它们提供了彼此之间的一对一映射。如何处理空值,当我运行第二个测试时,会出现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

我有以下两个类,它们提供了彼此之间的一对一映射。如何处理空值,当我运行第二个测试时,会出现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;
                }
            }
        }
    }
}

你在这里遇到了无限循环

如果您只是不想得到
null
s,请使用以下方法:

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

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

[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);
                    }
                }
            }
        }
    }
[TestFixture]
公共类测试员
{
[测试]
公共空间
{
var refs=新引用();
var x=新x(参考文献);
变量y=新的y(参考);
x、 Y=Y;
Assert.arame(x.Y,Y);
Assert.arame(y.X,X);
}
[测试]
public void SetYToNull()
{
var refs=新引用();
var x=新x(参考文献);
变量y=新的y(参考);
x、 Y=Y;
y、 X=零;
Assert.IsNull(x.Y);
Assert.IsNull(y.X);
}
}
公共类引用
{
私有IDictionary refs=新字典();
公共布尔包含(X,Y)
{
如果(!refs.ContainsKey(x))返回false;
如果(refs[x]!=y)返回false;
返回true;
}
公共作废删除(X X)
{
参考文献:移除(x);
}
公共无效添加(X,Y)
{
参考添加(x,y);
}
公共Y-Get(X X)
{
返回refs.ContainsKey(x)?refs[x]:空;
}
公共X得到(Y)
{
变量对=参考值,其中(r=>r.值==y);
返回pairs.Any()?pairs.FirstOrDefault().Key:null;
}
公共作废删除(Y)
{
X=Get(y);
如果(x!=null)
{
删除(x);
}
}
}
公共X类
{
私有只读参考文献;
公共X(参考文献)
{
this.refs=refs;
}
公共图书馆
{
get{return refs.get(this);}
设置
{
如果(值==null)
{
参考文献。删除(本);
}
其他的
{
如果(!refs.Contains(this,value))
{
参考添加(该值);
}
}
}
}
}
公共Y类
{
私人参考文献;
公共图书馆(参考文献)
{
this.refs=refs;
}
公共X X
{
get{return refs.get(this);}
设置
{
如果(值==null)
{
参考文献。删除(本);
}
其他的
{
如果(!refs.Contains(value,this))
{
参考添加(值,本);
}
}
}
}
}
工作正常:

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

            }
        }
    }
}

设置
y.X=null时,它将尝试将y.X设置为null,因为X不是null,而这反过来又尝试将(y.X).y设置为null,因为X中的y仍然不是null,并且。。。好吧,你明白了——一个无止境的循环

我对其进行了更改,以便在分配给成员变量的属性之前,先分配成员值

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

您想实现什么?当我将x.Y设置为null时,我希望x.Y和Y.x都为null,因为它们都相互引用,基本上我希望在两个对象之间保持双向引用。您可能希望重新考虑此设计。您可以删除此选项:
if(temp!=null)
因为在setter开始时,您检查
\ux!=值
,如果新值为
null
,则temp变量始终不为null。看看我的答案。