C# Inheritance: Static vs. Non-Static Field

2020-04-18 08:37发布

问题:

I have a library base class (Controller) and three sub-classes that inherit from Controller (Sensor, Output, and Environment) where:

public class Controller
{
   private SerialPort serial;
   private Sensor sensorSettings;
   private Output outputSettings;
   private Environment environmentSettings;       


   protected Dictionary<int, string> ErrorDescriptions
   { get{ this.errorDescriptions; } }

   protected SerialPort ControllerSerialPort
   { get{ this.serial; } }

   protected Sensor SensorSettings
   { get{ this.sensorSettings; } }

   // The other sub-class get properties.

   protected string SendReceive(string controllerCommand)
   { ... }

   ...
 }

 public class Sensor : Controller {...}
 ... // Other sub-classes

My question is this: Should I make the errorDescriptions static? These error descriptions will not change from controller to controller (i.e. static) but I wasn't sure what happens in the inherited classes. Will I have to refer to them as Sensor.errorDescription in the Sensor class or will it still be Controller.errorDescription?

EDIT

Wow, I just realized I messed up big time. Here's how it should be, I think:

private abstract class ControllerBasics
{
   protected SerialPort serial;  // The serial port to communicate with the controller.
   protected Dictionary<int, string> errorDescriptions = new Dictionary<int, string> {...};   // Possible errors for the controller (known and fixed). Won't change from controller to controller.
   public enum Sensors {One, Two, ...};   // Possible sensor selection.

   public string SendReceiveCommand(string command){...} // Method to send string command over "serial".       
}

public class OverallController : ControllerBasics // The controller class.
{       
   // Add top-level controller settings.
   private string controllerName = "Controller1"; // Have a property to get/set.
   private bool controllerON; // Controller on/off. Have property to get/set.
   ... // Other similar fields and methods.

   // Used to "sort" the controller's many settings/functions.
   private SensorSettings sensorSettings;  // Have get/set properties for these so I could do the following: overallControllerInstance.GetSensorSettingsProperty.SetActiveSensorCount(5);
   private OutputSettings outputSettings;
   private EnvironmentSettings environmentSettings;

   public OverallController(string name, string comPort, ...)  // Constructor.
   {
      // Basic settings initialization.
      // Create serial port.
      this.sensorSettings = new SensorSettings(this.serial);
      this.outputSettings = ...
}

public class SensorSettings : ControllerBasics // Class to hold the controller's specific sensor settings and their respective get/set methods. Not a new type of controller.
{
   private int activeSensorCount; // Have public method to get/set.
   ... // Others.

  public void SetActiveSensorCount(int sensorCount)
  {
     // Send command using inherited SendReceive().
  }
  ... // Others.
}

public class OutputSettings : ControllerBasics   // Same logic as SensorSettings.
{
   private string units; // Have public method to get/set.
   ... // Others.

  public string GetUnitType()  // Meters, mm, um...
  {
     // Send command using inherited SendReceive().
  }
  ... // Others.
}

public class EnvironmentSettings : ControllerBasics   // Same logic as SensorSettings.
{
   ...
}

So if errorDescriptions defined in ControllerBasics is known and fixed (and required in all derived classes) should I make it static or should I just leave it protected and each derived class will have it's own dictionary (i.e. this.errorDescriptions)?

回答1:

There would only be one static variable, however many subclasses you have. Is it meant to vary by subclass, or is it truly one global mapping? If it's the latter, then a static variable is appropriate. If not... well, there are various options, but you'd need to tell us what you're using the map for.



回答2:

If you only need one instance of the dictionary than yes, change it to protected static. Also you should use ConcurrentDictionary instead for thread safety.

In the derived classes you access the field using Controller.errorDescription



回答3:

Well, a private member won't be visible to your derived classes. You would need a protected member or property for that. Within the class, you can just refer to it as errorDescriptions or this.errorDescriptions.

I'd be extremely wary of having a static, protected member variable that isn't thread safe and can be mutated by derived classes. That's just asking for trouble.