WPF C#: Static classes, when to use them?

1    20 Jun 2018 22:03 by u/auto_turret

So, I've built a data logger device communicating via Modbus protocol. Works great, firmware is my field of somewhat expertise. I've been crash coursing C# for the past couple weeks, trying to get my head wrapped around object-oriented coding, in order to build myself an app to view the sensor data from my device as a continuous plotting chart. The device can broadcast sensor data from 8 different channels.

Only took me a weekend to get a demo up and running, but not utilizing any sort of OOP-like code, since I don't really know what the fuck I'm doing with OOP yet.. The code looked like a trad C garage-class code piece of crap.

I've been trying to follow the MVVM model, I have the different functional parts broken up: CaptureEngine.cs - has everything I need to extract the incoming sensor data. I simply pass it a baud rate and com port, run the connect function, and the engine updates the ChannelModel for 8 channels as the data logger sends it. We trigger an event to notify new data is available, so the ChannelModel is updated on every trigger.

ChartingEngine.cs - Uses the data from ChannelModel to plot a chart

ChannelModel.cs - Contains 8 channel labels (strings) and 8 channel present values (double). Contains an event to let the ChartEngine know new data is available, and to plot it. MeasureModel.cs - Simply a class with two properties, time and present value. This is the package I send the current channel data to the ChartEngine.

MainWindow.cs - Basically just initializes and starts the CaptureEngine and ChartEngine

ViewModel.cs - Contains properties of visible data, (channel_1_label_vm, channel_2_label_vm... etc). Also contains code for the visual elements such as buttons, textboxes, etc.

I'm wondering.. is making my ChannelModel a static class, so that all classes can see the channel data it contains, a good move? Because creating a non-static instance doesn't seem to work.. the other classes won't see it.

Now this all works just fine, but the whole static ChannelModel class seems like I'm misbehaving/not utilizing C# like I should be..

My question I'm hoping to get some insight into is, in what situations would you use a static class? Is it common for static classes to be used incorrectly/abused?

12 comments

2

Static classes are generally considered an anti pattern and have few and very specific uses cases (don't remember them of the top of my head). In your example you don't need a static class so u shouldn't use it. All you need to do is pass the instance of ChannelModel to the classes that use it. So let say your ViewModel.cs need ChannelModel you do something liked this.

 public class ViewModel 
    {
     ChannelModel  _channelModel ;
        public ViewModel (ChannelModel  channelModel)
        {
            _channelModel = channelModel;
        }
     }

You should look into Dependency Injection and Inversion of Control since is pretty much a standard now.

Dependency Injection (DI) vs. Inversion of Control (IOC)

0

Thanks for the reply. I'm drawing out my program for the umpteenth time, it is slowly starting to click I think..

I believe my trouble is, I keep reverting to thinking like I'm coding a microcontroller which keeps me running into roadblocks.

Referencing your code: I see what you did there, didn't realize I could pass along the whole instance and it's current state.

I believe now, if I put an event listener in that ViewModel constructor instead, and stick _channelModel = channelModel in a method that will call, it should listen for a newdata available event and update itself accordingly, so long as I've created a new ViewModel instance in my main program.

I'll give it a shot. Thanks man, that was super helpful. Going to check out the links you've provided.

0

IoC tends to turn out into very messy code and hard to reverse engineer. If you did not create the code yourself or were part of it then you are toast.

In a perfect world where programs are perfect, analysis done right and developers never make mistakes, then IoC is good. But the hard reality is that when you inherit code that you started but others took over and they tell you fix the bugs.

On top of that IoC, actually explodes the amount of code that you need exponentially to do the exact same job.

The sad reality is that if jump on this IoC bandwagon, your brain gets trapped that this is the only possible solution and you lose the ability into train your brain into creativity. You become slave of the code, instead of the master.

0

On top of that IoC, actually explodes the amount of code that you need exponentially to do the exact same job.

Exactly what I observe. Coming from firmware programming where sometimes your usable ram is measured in BYTES, I kept initially gravitating towards trying to make every bit and byte count. Well, it just don't work that way in Windows app coding..

I can see how it could be quite helpful in swapping modules down the road, and my small app so far seems it could be easily followed and understood without excessive commentary.

0

Static classes can sometimes make sense, but often they are just a quick and dirty hack and they make your code harder to extend in the future.

Only if there's no way in hell that you could ever use a second instance of something, only then a static class makes sense.

But 99.9% of the time, you can actually Benefit from allowing more than one instance.

Often, beginners initially like static classes, because you don't have to pass the objects to all your other objects, which is tedious.

But there is a middle Ground:

public class ChannelModel
{
    public static ChannelModel Default { get; } = new ChannelModel();
    ...
}
public class ViewModel
{
    ChannelModel ChannelModel { get; set; }
    public ViewModel(ChannelModel ChannelModel = ChannelModel.Default)
    {
        this.ChannelModel = ChannelModel;
    }
}

Now you have your "static" instance that you don't have to pass around, but you can have multiple instances, since the class is not static.

0

Cool man, I did use something exactly like that to access my Receive() in my CaptureEngine class from my RS232Functions class. Something to the effect of

private RS232Functions _instance = new RS232Functions(); public RS232Functions Instance { get { return _instance; } }

and

// Create function call on data received serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(CaptureEngine.Instance.Recieve);

to use it.. so far that's been working out for me.

0

Thanks dude! I knew how static classes worked, but that work around is really useful!

0

If you start with static classes first then you will end up having code that is not extendable and thread safe. Also you can always nail down a dynamic class as static like a singleton.

I tend to initialize static classes at my Main() first. This way I have a predictable place where the code gets initialized.

0

I've re-written the darn thing again, but this time using the dependency inversion principle. NOW things make more sense.. high level modules don't depend on lower level modules, but rather abstractions that don't rely on details.

Works for everything BUT the serialport functions. It appears it must be static or my port won't stay open.

0

Scratch the last comment, got rid of the static from SerialPort too. I think I've pretty much got this concept down, now. Been banging my head for a month, then finally came to you guys for advice. Turns out that's exactly what I needed!

0

Nice to hear.

0

Static class -> When you only want one of something.

If you create a level in a game as a class, you (typically) only want one instance of that level.