Search code examples
c#classinheritancepropertiesenumerable

How do we assign a current property to be equal to new parameter and then remove it when a new value is assined?


The test should check when a train is assigned to a line he losts its previous line. The class Train should implement this test in the function public void AssignTo(ILine l) by following those steps (they need to be respected):

  1. Current assignment = l1
  2. l1.Trains contains THIS
  3. need to remove THIS from l1.trains
  4. need to change current line and add train to new line

    internal class Train : ITrain
    {
        internal Train(string name, Company company)
        {
            this.Name = name;
            this.Company = company;
        }

        public string Name
        {
            get;
        }

        public ICompany Company
        {
            get;
        }

        public ILine Assignment
        {
            get;
            private set;
        }

        public void AssignTo(ILine l)
        {
            //Current assignment = l1
            var l1 = Assignment;

            //l1,Trains contains THIS
            this.AssignTo(l1.train)

            //need to remove THIS from l1.trains
            ((List<Train>)l1.Trains).Remove(this);

            //need to change current line and add train to new line
            ((List<Train>)l.Trains).Add(this);
            Assignment = l;
           
        }
    }
}

[Test]
        public void T2_when_a_train_is_assigned_to_a_line_he_losts_its_previous_line()
        {
            ICity s = CityFactory.CreateCity("Paris");
            ICompany c = s.AddCompany("SNCF");
            ILine l1 = s.AddLine("RER A");
            ILine l2 = s.AddLine("RER B");
            ITrain t1 = c.AddTrain("RER1");

            t1.AssignTo(l1);
            t1.Assignment.Should().BeSameAs(l1);

            t1.AssignTo(l2);
            t1.Assignment.Should().BeSameAs(l2);
            l1.Trains.Count().Should().Be(0);
            l2.Trains.Single().Should().BeSameAs(t1);
        }


Solution

  • The problem with your current interfaces are that ILine.Trains is an IEnumerable, and you can't really remove something from an IEnumerable. In your code, you have assumed that it will always be a List, which you shouldn't really do, but if you can't change the type of ILine.Trains then I guess that's the only way.

    Anyway, the reason why your code doesn't work is that you are recursively calling AssignTo for some reason. You should remove this call:

    public void AssignTo(ILine l)
    {
        var l1 = Assignment;
    
        // remove this line
        // this.AssignTo(l1.train)
    
        ((List<Train>)l1.Trains).Remove(this);
    
        ((List<Train>)l.Trains).Add(this);
        Assignment = l;
    
    }
    

    Although this isn't required, (it seems to be one of your requirements), you need to check whether l1.Trains contains this first:

    var l1 = Assignment;
    
    if (l1.Trains.Contains(this)) {
        ((List<Train>)l1.Trains).Remove(this);
    }
    
    ((List<Train>)l.Trains).Add(this);
    Assignment = l;