Resolved how to best use "public"read-write properties of event-driven applications

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
I am trying to convert a working Console UI application into a WPF one. I use an s/w library from Varian Medical Systems, called Velocity API, whose documentation is scarce and somewhat misleading. Velocity API hardcoded logic is built on context. My Console UI application calls several sequential Velocity API methods. However, a GUI must allow for consistent, event-driven actions.
I need one, maybe more, “state” variables to update the context expected by each Velocity API method. I declare most of the properties “public” and accessed through {get; set;}. I do not have a clear understanding of how such properties work. For example, one of my “state” variables is a Boolean variable called “FirstPass” that Is to distinguish between the first time a patient’s CT scan has been selected and the user’s second or n_th choice. Failure to provide the expected context causes the system to throw a memory access violation exception upon calling a Velocity method. The above-mentioned property is defined as follows:
C#:
private bool _firstPass;
public bool FirstPass
  {
get {return _firstPass;}
set {_firstPass = value;}
 }
This property must be set “true” at the application start time and when another patient‘s data is loaded. It must be set “false” after a CT scan has been selected. Unluckily, the runtime value of such a state variable, which I check through the debugger, Is not what I expect. I attribute that to my not clear understanding of the {get; set;} mechanism. I am afraid I am not using it correctly. I would appreciate some clarifying explanations and examples. Thank you very much in advance.
 
Last edited by a moderator:

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
I think what you are missing is some of the basic object oriented programming principles due to your background as Medical Physicist instead of as a Programmer. I'll try to give a crash course. Hopefully some other people in this forum can provide a better explanation of things.

Let's start off with a class with it's internal state exposed to the world:
C#:
class LightBulb
{
    public bool isOn;
}

One of the key ideas of object oriented programming is encapsulation. This is basically to say that the internal workings of a class should be hidden away from the view of users of that object. You don't want users to know that your light bulb has an internal isOn variable that keeps track of whether the light bulb is on or off. By exposing that variable, you are locking in that knowledge into your users. What if in the future, you want to change your light bulb implementation to hold values from 0 to 100 because it's a dimmable light bulb? You break all your users.

To prevent your users from programming against your internal state, you have them program against at interface. (I'll let you do your own research and form your own opinions later about whether getters and setters are actually antipatterns and should be avoided as part of a programming interface.) Or as more modern object oriented programmers now say, you send an message to an object. So the classical Java approach to this is to have getters and setters:
C#:
class LightBulb
{
    private bool isOn;

    public void setIsOn(bool value)
    {
        isOn = value;
    }

    public bool getIsOn()
    {
        return isOn;
    }
}
and callers would have to write:
C#:
var lightbulb = new Lightbulb();
lightbulb.setIsOn(true);
Console.WriteLine("IsOn is {0}", lightbulb.getIsOn());

So going with our hypothetical change to use value of 0 to 100 for the internal state we can write:
C#:
class LightBulb
{
    private int brightness;

    public void setIsOn(bool value)
    {
        setBrightness(value ? 100 : 0);
    }

    public bool getIsOn()
    {
        return brightness > 0;
    }

    public void setBrightness(int value)
    {
        brightness = value;
    }

    public int getBrightness()
    {
        return brightness;
    }
}
and our callers code wouldn't change:
C#:
var lightbulb = new Lightbulb();
lightbulb.setIsOn(true);
Console.WriteLine("IsOn is {0}", lightbulb.getIsOn());

Looks pretty verbose, with those explicit Java-esque setters and getters. Early versions of C# has a more compact way of writing the same things:
C#:
class LightBulb
{
    private bool isOn;

    public IsOn
    {
        set
        {
            isOn = value;
        }

        get
        {
            return isOn;
        }
    }
}
and callers would write:
C#:
var lightbulb = new Lightbulb();
lightbulb.IsOn = true;
Console.WriteLine("IsOn is {0}", lightbulb.IsOn);

Or conserving lines as one of the early style conventions:
C#:
class LightBulb
{
    private bool isOn;

    public bool IsOn
    {
        set { isOn = value; }
        get { return isOn; }
    }
}

The above tends to be boilerplate code. So the next iteration of the C# language came up with automatic properties to cut down on the boilerplate. The compiler would supply the backing variable isOn. (Actually it has a different naming convention for the backing variable to prevent name collisions.)
C#:
class LightBulb
{
    public bool IsOn { get; set; }
}

Or going to our alternate light bulb implementation we have:
C#:
class Lightbulb
{
    public int Brightness { get; set; }
    
    public bool IsOn
    {
        set { Brightness = value ? 100 : 0 }
        get { return Brightness > 0; }
    }
}

So what value is there to these getters and setters if all it looks like is that you are just adding an extra layer to access an internal variable albeit an internal variable that callers are not supposed to know about. (See what I mean about the potential for getters/setters being an antipattern?) Well since the properties are just essentially just methods under the covers, you can do extra work in them. Like in the case of our dimmable light bulb, we don't want people setting the brightness above 100 or below 0. So we re-write it again with a backing variable and do some validation on the setter:

C#:
class Lightbulb
{
    public const int MinBrightness = 0;
    public const int MaxBrightness = 100;

    private int _brightness;
    public int Brightness
    {
        get { return _brightness; }

        set
        {
            if (value < MinBrightness || value > MaxBrightness)
                throw new ArgumentOutOfRange($"value cannot be less than {MinBrightness} or greater than {MaxBrightness}");

            _brightness = value;
        }
    }
    
    public bool IsOn
    {
        set { Brightness = value ? MaxBrightness : MinBrightness }
        get { return Brightness > MinBrightness; }
    }
}

Very likely, while you were going through your WPF learning curve, you were seeing various properties participating in the IPropertyChangeNotify notification whenever the setters were called.

If you look at some of the older C# sample code that Microsoft has, you'll often see them implementing lazy initialization in the getters.

(Again, I'll let you do your own research and come to your own opinions whether properties should do work, and whether properties should throw exceptions.)
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
I think what you are missing is some of the basic object oriented programming principles due to your background as Medical Physicist instead of as a Programmer. I'll try to give a crash course. Hopefully some other people in this forum can provide a better explanation of things.

Let's start off with a class with it's internal state exposed to the world:
C#:
class LightBulb
{
    public bool isOn;
}

One of the key ideas of object oriented programming is encapsulation. This is basically to say that the internal workings of a class should be hidden away from the view of users of that object. You don't want users to know that your light bulb has an internal isOn variable that keeps track of whether the light bulb is on or off. By exposing that variable, you are locking in that knowledge into your users. What if in the future, you want to change your light bulb implementation to hold values from 0 to 100 because it's a dimmable light bulb? You break all your users.

To prevent your users from programming against your internal state, you have them program against at interface. (I'll let you do your own research and form your own opinions later about whether getters and setters are actually antipatterns and should be avoided as part of a programming interface.) Or as more modern object oriented programmers now say, you send an message to an object. So the classical Java approach to this is to have getters and setters:
C#:
class LightBulb
{
    private bool isOn;

    public void setIsOn(bool value)
    {
        isOn = value;
    }

    public bool getIsOn()
    {
        return isOn;
    }
}
and callers would have to write:
C#:
var lightbulb = new Lightbulb();
lightbulb.setIsOn(true);
Console.WriteLine("IsOn is {0}", lightbulb.getIsOn());

So going with our hypothetical change to use value of 0 to 100 for the internal state we can write:
C#:
class LightBulb
{
    private int brightness;

    public void setIsOn(bool value)
    {
        setBrightness(value ? 100 : 0);
    }

    public bool getIsOn()
    {
        return brightness > 0;
    }

    public void setBrightness(int value)
    {
        brightness = value;
    }

    public int getBrightness()
    {
        return brightness;
    }
}
and our callers code wouldn't change:
C#:
var lightbulb = new Lightbulb();
lightbulb.setIsOn(true);
Console.WriteLine("IsOn is {0}", lightbulb.getIsOn());

Looks pretty verbose, with those explicit Java-esque setters and getters. Early versions of C# has a more compact way of writing the same things:
C#:
class LightBulb
{
    private bool isOn;

    public IsOn
    {
        set
        {
            isOn = value;
        }

        get
        {
            return isOn;
        }
    }
}
and callers would write:
C#:
var lightbulb = new Lightbulb();
lightbulb.IsOn = true;
Console.WriteLine("IsOn is {0}", lightbulb.IsOn);

Or conserving lines as one of the early style conventions:
C#:
class LightBulb
{
    private bool isOn;

    public bool IsOn
    {
        set { isOn = value; }
        get { return isOn; }
    }
}

The above tends to be boilerplate code. So the next iteration of the C# language came up with automatic properties to cut down on the boilerplate. The compiler would supply the backing variable isOn. (Actually it has a different naming convention for the backing variable to prevent name collisions.)
C#:
class LightBulb
{
    public bool IsOn { get; set; }
}

Or going to our alternate light bulb implementation we have:
C#:
class Lightbulb
{
    public int Brightness { get; set; }
   
    public bool IsOn
    {
        set { Brightness = value ? 100 : 0 }
        get { return Brightness > 0; }
    }
}

So what value is there to these getters and setters if all it looks like is that you are just adding an extra layer to access an internal variable albeit an internal variable that callers are not supposed to know about. (See what I mean about the potential for getters/setters being an antipattern?) Well since the properties are just essentially just methods under the covers, you can do extra work in them. Like in the case of our dimmable light bulb, we don't want people setting the brightness above 100 or below 0. So we re-write it again with a backing variable and do some validation on the setter:

C#:
class Lightbulb
{
    public const int MinBrightness = 0;
    public const int MaxBrightness = 100;

    private int _brightness;
    public int Brightness
    {
        get { return _brightness; }

        set
        {
            if (value < MinBrightness || value > MaxBrightness)
                throw new ArgumentOutOfRange($"value cannot be less than {MinBrightness} or greater than {MaxBrightness}");

            _brightness = value;
        }
    }
   
    public bool IsOn
    {
        set { Brightness = value ? MaxBrightness : MinBrightness }
        get { return Brightness > MinBrightness; }
    }
}

Very likely, while you were going through your WPF learning curve, you were seeing various properties participating in the IPropertyChangeNotify notification whenever the setters were called.

If you look at some of the older C# sample code that Microsoft has, you'll often see them implementing lazy initialization in the getters.

(Again, I'll let you do your own research and come to your own opinions whether properties should do work, and whether properties should throw exceptions.)
Thank you very much.
I have completed a C# Console UI application that works but I feel uneasy at implementing the same functionalities as a WPF application because I do not know of any appropriate technique to develop and especially debug event-driven applications.
How can I make the various event handlers communicate? I miss the old style to pass parameters by value or by reference.
If two event handlers are in two different files but belong to the same namespace, how can I make them share a Vector or a List<Object>?
Assume Event-handler1 handles the user choice of a List element.
Event-handler2 has to access the selected List item and use it to do other things.
According to your mini-course, I should declare the List<Object> through a property with {get; set:}.
Can you please provide an example in line with the problem I have explained above?
Thank you so much
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Inside my class "PTAccess" I have a state variable declared as follows:

private bool _firstPass ;
public bool FirstPass
{
get { return _firstPass; }
set { _firstPass = value; }

}


Inside the same class PTAccess I have a method that changes the content of the state variable as follows:

public void ResetVelocityContext()
{
engine.unloadPatient();
engine.unloadPrimaryVolume();
AppDomain.CurrentDomain.ProcessExit += (source, data) => { engine.logout(); };
FirstPass = true;
}


My ignorance suggests that I should not define an instance of class PTAccess to change the content of FirstPass because the method that does that and the state variable FirstPass are both defined inside the same class PTAccess. TRUE/FALSE?
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
True. You should use the current instance that you already have, not instantiate another instance.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Shall I define my state variable as "public static" or simply "public" to allow read and write access to the state variable from another class that is in another file but belongs to the same namespace?
That state variable is defined inside a public class "PTAccess".
To access the state variable from another class in another file I have to do:

var pt = new PTAccess;
pt.FirstPass = false;


Moreover, that state variable must be initialized as "true".
How shall I initialize it from a method that belongs to the same class PTAccess as the
definition of the state variable?
May I do simply
FirstPass = true;
or
_firstPass = true

Thank you so much
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
Play with this for a while:
C#:
using System;

class Foo
{
    public bool Ready { get; set; } = true;

    public void DoWork()
    {
        if (Ready != true)
            throw new InvalidOperationException("Need to be in a ready state");

        Ready = false;
    }
}

class Bar
{
    Foo _foo;

    public Bar(Foo foo)
    {
        _foo = foo;
    }

    public void DoIt()
    {
        _foo.DoWork();
    }

    public void DoItAgain()
    {
        _foo.Ready = true;
        DoIt();
    }
}

class Program
{
    static void Main()
    {
        var foo = new Foo();
        var bar = new Bar(foo);

        Console.WriteLine(foo.Ready);
        bar.DoIt();
        Console.WriteLine(foo.Ready);
        bar.DoItAgain();
        Console.WriteLine(foo.Ready);
    }
}

What you see there with the Bar constructor that takes a Foo is called dependency injection. It makes sure that both the Main() and the Bar instance are both talking to the same instance.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Thank you.
I cannot run your example as this compiler display the following error:

Error CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point. Wpf-SkyDiver C:\Users\mauram\Desktop\Wpf-SkyDiver\MainWindow.xaml.cs 39

I see the class Bar defines an instance of class Foo that ic called _foo.
The constructor of class Bar takes as input another instance of class Foo called foo. then is assigns the object foo to the object _foo.

Isn't _foo called the backfield?
Shall I use a backfield with my FirstPass property?
To initialize FirtstPass to 'true" shall I do the following

<
private bool _firstPass = true?
public bool FirstPass
{
get { return _firstPass; }
set { _firstPass = value; }

}
/>
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
The code there was mean to be run in a standalone console app so that you could play with it a bit and see how that pieces fit together before trying to do the same in WPF.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
I see the class Bar defines an instance of class Foo that ic called _foo.
Unfortunately no. Line 18 just declares a member variable that can hold a reference to an instance of Foo. It doesn't define or declare an instance of Foo.
Isn't _foo called the backfield?
It's callled a member variable or instance variable. A member variable can be used as a backing field for a property.
Shall I use a backfield with my FirstPass property?
To initialize FirtstPass to 'true" shall I do the following

<
private bool _firstPass = true?
public bool FirstPass
{
get { return _firstPass; }
set { _firstPass = value; }

}
/>
You don't really need a backing field unless you'll eventually want FirstPass to participate in the INotifyPropertyChanged implementation. If you don't, you could simply use:
C#:
public bool FirstPass { get; set; } = true;
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
The code there was mean to be run in a standalone console app so that you could play with it a bit and see how that pieces fit together before trying to do the same in WPF.
I downloaded and pasted your code into WPF application generated by Visual Studio.
It should be a console application.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Unfortunately no. Line 18 just declares a member variable that can hold a reference to an instance of Foo. It doesn't define or declare an instance of Foo.

It's callled a member variable or instance variable. A member variable can be used as a backing field for a property.

You don't really need a backing field unless you'll eventually want FirstPass to participate in the INotifyPropertyChanged implementation. If you don't, you could simply use:
C#:
public bool FirstPass { get; set; } = true;
Thank you.
FIrstPass is only used to keep track of whether a CT volume has been loaded as "primary volume". No information can be accessed from any CT volume until it is loaded as "primary volume". When the user selects another CT from the displayed list I have to unload the primary volume, if any, before I can select another CT as primary.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
Does the first pass state even have to be known by the users of the PTAccess class? In other words, why does FirstPass need to be public? If it does not need to be public, then you can just get by with a member variable.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
How can I make the various event handlers communicate? I miss the old style to pass parameters by value or by reference.
If two event handlers are in two different files but belong to the same namespace, how can I make them share a Vector or a List<Object>?
Assume Event-handler1 handles the user choice of a List element.
Event-handler2 has to access the selected List item and use it to do other things.
According to your mini-course, I should declare the List<Object> through a property with {get; set:}.
Can you please provide an example in line with the problem I have explained above?
Typically, all the event handlers would be part of the same class, and normally they would also be all be the same instance.

The fact that you are talking about event handlers instead of command handlers indicates that you are trying to write WPF code using the WinForms style programming, instead of the WPF recommend approach of using MVVM (Model-View-View Model) pattern.

If you were using MVVM with WPF, then typically the command handlers would have either the view model or the model as a dependency that is injected into them. Or alternately, the command handlers would simply be rerouted to methods on the view model.

In any case, whether you are using WinForms style code, or MVVM, there will be some object instance that holds the shared state that the event handlers or command handlers would have access to.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Does the first pass state even have to be known by the users of the PTAccess class? In other words, why does FirstPass need to be public? If it does not need to be public, then you can just get by with a member variable.
FirstPass is declared inside class PTAccess. It is accessed in read / write mode by some methods inside class PTAccess simply doing:
FirstPass = false;
or
if(!FirstPass) {unload current PrimaryVolume};

It is also accessed by a method inside class MainWindow as follows:

PTAccess pt = new PTAccess();
pt.FirstPass = false;


Questions
  1. should FirstPass be declared "public static" or simply "public"? This variable has to be kept in memory for the entire duration of the application. So it cannot be a volatile memory.
  2. When FirstPass is accessed by a method of class MainWindow (in another file) I have to create an instance of class PTAccess to do that. Which one of the following two statements is correct?
PTAccess pt = new PTAccess(); or var pt = new PTAccess();


Thank you so much
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
Declaring a variable (or property) public static is basically declaring a global variable. Global variables and singletons should be avoided to help keep code testable and maintainable.

var pt = new PTAccess(); and PTAccess pt = new PTAccess(); as well as PTAccess pt = new(); are all equivalent.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
If I declare FirstPass simply as "public" with {get;set} am I sure that it can be accessed in both read/write mode by methods that belong to another class in another file but are still part of the same namespace?

Thank you
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
When FirstPass is accessed by a method of class MainWindow (in another file) I have to create an instance of class PTAccess to do that. Which one of the following two statements is correct?
Neither one.

The most correct thing to do is to inject an instance of PTAccess into the instance of MainWindowViewModel.

The next passable thing is to
inject an instance of PTAccess into the instance of MainWindow.

What will work is to create an instance of PTAccess in the instance of MainWindow.

In all cases above, store it in an instance variable.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,251
Location
Chesapeake, VA
Programming Experience
10+
If I declare FirstPass simply as "public" with {get;set} am I sure that it can be accessed in both read/write mode by methods that belong to another class in another file but are still part of the same namespace?
Yes. Even if they are in different name spaces, you can still get access to them by fully qualifying the class name.
 

mauede

Well-known member
Joined
Sep 1, 2021
Messages
103
Location
Northwood - UK
Programming Experience
Beginner
Thank you very much for all your help and patience.
I could make some progress despite the behaviour of Velocity API that is not documented and quite erratic.
I have attached my first GUI.
It was hard to display the 4th column (the one with yellow background). Not because of my gaps with C# and WPF. Instead because of the unexpected and undocumented behaviour of Velocity API methods. I just achieved this result by trial & error with Velocity API methos.
I have not understood the cause of my previous several failures.
The next challenge will come from WPF. I will have to display a list of strings on a fifth ListBox whose items will have to allow editing.
I am posting another question explaining my problem to get some guidelines.
Thank you again
 

Attachments

  • Screenshot 2022-03-05 at 20.36.30.png
    Screenshot 2022-03-05 at 20.36.30.png
    917.7 KB · Views: 5
Top Bottom