0

I have two variables CarsSelected and PlanesSelected. If someone sets one of them I want the other variable to be set to the opposite value, so if one is true, the other one has to be false and vice versa. Therefore both variables in the end are always different. My problem is my code goes to into infinite loop when changing any value. How to fix it?

public class MyClass
{
    private bool _carsSelected;
    private bool _planesSelected;
    
    public bool CarsSelected
    {
        get => _carsSelected;
        set
        {
            _carsSelected= value;
            PlanesSelected= !_carsSelected;
        }
    }
    
    public bool PlanesSelected
    {
        get => _planesSelected;
        set
        {
            _planesSelected= value;
            CarsSelected= !_planesSelected;
        }
    }
    
    public MyClass()
    {
        CarsSelected= false;
        PlanesSelected= false;
    }
}
Palle Due
  • 5,929
  • 4
  • 17
  • 32
Arie
  • 3,041
  • 7
  • 32
  • 63
  • 4
    Set the backing fields and not the properties (from within the property setters). – ProgrammingLlama Mar 12 '21 at 10:07
  • @Llama i thought this is the same or havent noticed that – Arie Mar 12 '21 at 10:08
  • 2
    `CarsSelected = ` will trigger the property setter. `_carsSelected = ` won't, because you're not setting the property. – ProgrammingLlama Mar 12 '21 at 10:08
  • 5
    Bad design. You should have a property called Selection and an enum type SelectionType { Car, Plane, ... }. (names are just a sugestion). – Marius Bancila Mar 12 '21 at 10:11
  • Agreed - if the two properties can never have the same value, then there's no point in having two properties to begin with. Just have one, which makes it clear what has been selected. – ADyson Mar 12 '21 at 10:16
  • Does this answer your question? [I am getting into infinite loop in property setter](https://stackoverflow.com/questions/16154873/i-am-getting-into-infinite-loop-in-property-setter) – Qwertyluk Mar 12 '21 at 11:10

3 Answers3

6

You only need one backing field (note the ! operators in the PlanesSelected property):

public class MyClass
{
    private bool _carsSelected;

    public bool CarsSelected
    {
        get => _carsSelected;
        set
        {
            _carsSelected= value;
        }
    }

    public bool PlanesSelected
    {
        get => !_carsSelected;
        set
        {
            _carsSelected = !value;
        }
    }


    public MyClass()
    {
        CarsSelected= false;
        PlanesSelected= false;
    }
}

You can even use an auto property for CarsSelected with this approach. But actually, instead of two bools, this looks more like you need an enum:

public enum TranportDevice
{
 Car,
 Plane
}

public class MyClass
{
   public TransportDevice SelectedTransportDevice {get;set;}
}
SomeBody
  • 7,515
  • 2
  • 17
  • 33
3

To provide an alternative to the other answers, this makes your code much more expandable. If you need to add a new property (for example TrainsSelected) then it's much easier to do.

public enum SelectedType
{
    None,
    Cars,
    Planes
}

public class MyClass
{
    private SelectedType _selectedType = SelectedType.None;

    public bool CarsSelected
    {
        get => _selectedType == SelectedType.Cars;
        set => _selectedType = value ? SelectedType.Cars : SelectedType.None;
    }    

    public bool PlanesSelected
    {
        get => _selectedType == SelectedType.Planes;
        set => _selectedType = value ? SelectedType.Planes : SelectedType.None;
    }
}

Of course, it depends on what you want to use those properties for. You may be able to get away with just the enum and a variable to store which one is selected.

DavidG
  • 113,891
  • 12
  • 217
  • 223
  • This should be the accepted answer. It's better with enum: so you are prepared in case there will be additional props. – Ergis Mar 12 '21 at 10:52
2

You should set the backing fields from within the property setters, so that you avoid triggering the other property's setter:

private bool _carsSelected;
private bool _planesSelected;

public bool CarsSelected
{
    get => _carsSelected;
    set
    {
        _carsSelected= value;
        _planesSelected= !_carsSelected;
    }
}

public bool PlanesSelected
{
    get => _planesSelected;
    set
    {
        _planesSelected= value;
        _carsSelected= !_planesSelected;
    }
}

Though since they are always opposites of each other, it doesn't seem like you need backing fields - one should suffice for both properties. As I write this an answer has been added to that effect, so I won't add it to mine.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86