I am new to c# and object coding so please be gentle....
I have a class call LED, see below:
public sealed class LED
{
public GpioPinValue ReqPinValue { get; set; } //Enable/Disable LED
public bool Flashing { get; set; } //Does the LED flash
public GpioPin Pin { get; set; }
public int flashingPeriod { get; set; } //Period to flash in seconds
private GpioPinValue value; //Pin value (high/low)
private int flashCount = 0; //Times we have entered the timer loop
public LED()
{
}
public void UpdateLED()
{
int timesToCycle = 0;
if (ReqPinValue == GpioPinValue.Low)
{
if (Flashing)
{
timesToCycle = flashingPeriod * 2;
if (flashCount == timesToCycle)
{
value = (value == GpioPinValue.High) ? GpioPinValue.Low : GpioPinValue.High;
Pin.Write(value);
flashCount = 0;
}
else
flashCount++;
}
else
{
Pin.Write(GpioPinValue.Low);
}
}
else
{
Pin.Write(GpioPinValue.High);
}
}
}
In another class I create four instances of this LED class for 4 different Status LED'S.
public sealed class StatusLED
{
private const int RUN_LED = 4;
private const int IO_LED = 17;
private const int NET_LED = 27;
private const int FAULT_LED = 22;
public LED RunLed = new LED();
public LED IOLed = new LED();
public LED NetLed = new LED();
public LED FaultLed = new LED();
private GPIO GPIO = new GPIO();
private GpioController gpioController;
private ThreadPoolTimer timer;
public void InitStatusLED()
{
gpioController = GPIO.InitGPIO();
if (gpioController == null)
{
Debug.WriteLine("Failed to find GPIO Controller!");
//TODO proper error handling although this should never happen
}
else
{
//Setup the default parameters for the LEDS (ie flashing or non-flashing)
RunLed.Flashing = false;
IOLed.Flashing = false;
NetLed.Flashing = false;
FaultLed.Flashing = false;
RunLed.flashingPeriod = 0;
IOLed.flashingPeriod = 0;
NetLed.flashingPeriod = 0;
FaultLed.flashingPeriod = 0;
RunLed.Pin = GPIO.InitOutputPin(gpioController, RUN_LED);
IOLed.Pin = GPIO.InitOutputPin(gpioController, IO_LED);
NetLed.Pin = GPIO.InitOutputPin(gpioController, NET_LED);
FaultLed.Pin = GPIO.InitOutputPin(gpioController, FAULT_LED);
//Turn the LED's on to Start
RunLed.ReqPinValue = GpioPinValue.Low;
IOLed.ReqPinValue = GpioPinValue.Low;
NetLed.ReqPinValue = GpioPinValue.Low;
FaultLed.ReqPinValue = GpioPinValue.Low;
timer = ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick, TimeSpan.FromMilliseconds(500));
}
}
private void Timer_Tick(ThreadPoolTimer timer)
{
RunLed.UpdateLED();
IOLed.UpdateLED();
NetLed.UpdateLED();
FaultLed.UpdateLED();
}
}
I now want to set the field "ReqPinValue" for these instances in the StatusLED class from another class using the code below
private StatusLED statusLED = new StatusLED();
statusLED.RunLed.ReqPinValue = GpioPinValue.Low;
I get the following error:
Error: Type '....' contains externally visible field '....' Fields
can be exposed only by structures.
I can see it doesn't like the line below being public, how can I can access a parameter of this instance from another class without making it public?
public LED RunLed = new LED();
You can make these properties rather than fields:
public LED RunLed {get;set;}
public LED IOLed {get;set;}
public LED NetLed {get;set;}
public LED FaultLed {get;set;}
Then, in your InitStatusLED method, initialize them:
public void InitStatusLED()
{
gpioController = GPIO.InitGPIO();
if (gpioController == null)
{
Debug.WriteLine("Failed to find GPIO Controller!");
//TODO proper error handling although this should never happen
}
else
{
//Setup the default parameters for the LEDS (ie flashing or non-flashing)
RunLed = new LED(GPIO.InitOutputPin(gpioController, RUN_LED));
IOLed = new LED(GPIO.InitOutputPin(gpioController,IO_LED));
//And so on
But wait - your LED class doesn't have a constructor that accepts a GpioPin. Let's fix that too:
public sealed class LED
{
public GpioPinValue ReqPinValue { get; set; } //Enable/Disable LED
public bool Flashing { get; set; } //Does the LED flash
public GpioPin Pin { get; set; }
public int flashingPeriod { get; set; } //Period to flash in seconds
private GpioPinValue value; //Pin value (high/low)
private int flashCount = 0; //Times we have entered the timer loop
public LED(GpioPin pin)
{
Pin = pin;
Flashing = false;
flashingPeriod = 0;
ReqPinValue = GpioPinValue.Low;
}
And see how we've eliminated a whole load of repetitive code from you InitStatusLed method too.
Having done all of this, go back and look at your properties again. For those which should only be set by the class itself, and not by any other code using the class, make the setters private:
public GpioPin Pin { get; private set; }
I want to create configuration for my application using static classes.
Firstly please forgive my ignorance, I'm not a full time c# dev. I come from a Ruby/Javascript world where dynamic access to constants & variables is trivial.
Whether or not this is the right approach here I'm not 100% at the moment. Would be greatful of other suggested approaches.
I have the following static class setup for my config:
public static class Config
{
public static class MaterialQuality
{
public static class Low
{
public const float Value = 0.1f;
public const int Cost = 10;
}
public static class Medium
{
public const float Value = 0.2f;
public const int Cost = 20;
}
public static class High
{
public const float Value = 0.2f;
public const int Cost = 40;
}
}
}
I then have a class Material, which is passed an enum value relating to the aboves types Low,Medium,High.
The reason for the enum in unity this gives a quick way for devs to provide level designers with an option list for a an object.
So by choosing an enum value the level designer can set the properties stored in the config without actually having to enter the values directly onto the object. The values are set against the object when it is initialised.
In the constructor I want to set member variables for Cost & Value from the static config values for the MaterialQuality enum value passed.
public enum MaterialQuality
{
Low,Medium,High
}
public class Material
{
private int Cost;
private float Value;
Material(MaterialQuality quality) {
Cost = Config.MaterialQuality.<quality>.Cost;
Value = Config.MaterialQuality.<quality>.Value;
//in Javascript I'd use associative array access to the object
Cost = Config.MaterialQuality[quality].Cost;
//in Ruby we have const_get() on classes.
Cost = Config.MaterialQuality.const_get(quality).Cost
}
}
The main reason for this approach is to provide single place for configuration & provide a fairly simple way for a non technical person to make changes to parts of the application without having to delve into the main classes. Also it allows me to take advantage of the constants being available in intellisense.
I'm a fan of using dictionaries for this type of configuration.
void Main()
{
var config = Config.Qualities[MaterialQualities.Low];
var cost = config.Cost;
var value = config.Value;
}
public static class Config
{
public static Dictionary<MaterialQualities, MaterialQuality> Qualities =
new Dictionary<MaterialQualities, MaterialQuality>
{
{ MaterialQualities.Low, new MaterialQuality { Value = 0.1F, Cost = 10 }},
{ MaterialQualities.Medium, new MaterialQuality { Value = 0.2F, Cost = 20 }},
{ MaterialQualities.High, new MaterialQuality { Value = 0.2F, Cost = 40 }},
};
}
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
public enum MaterialQualities
{
Low, Medium, High
}
Probably better approach would be:
public static class Config
{
public class Material
{
public Material(float value, int cost){
Value = value;
Cost = cost;
}
public float Value {get; private set;}
public int Cost {get; private set;}
public Material GetFor(MaterialQuality quality){
switch(quality){
case MaterialQuality.Low: return new Material(0.1f, 10);
case MaterialQuality.Medium: return new Material(0.2f, 20);
case MaterialQuality.High: return new Material(0.2f, 40);
}
throw new Exception("Unknown material quality " + quality);
}
}
}
and later you can use that:
//....
Material materialData = Material.GetFor(quality);
Cost = materialData.Cost;
Value = materialData.Value;
//...
I would use a struct and static properties in MaterialQuantity instead of an enum. Something like the following:
public struct MaterialQualityInfo
{
public MaterialQualityInfo( float value, int cost )
{
Value = value;
Cost = cost;
}
public float Value { get; private set; }
public int Cost { get; private set; }
}
public static class Config
{
public static class MaterialQuality
{
public static MaterialQualityInfo Low
{
get { return new MaterialQualityInfo( 0.1f, 10 ); }
}
public static MaterialQualityInfo Medium
{
get { return new MaterialQualityInfo( 0.2f, 20 ); }
}
public static MaterialQualityInfo High
{
get { return new MaterialQualityInfo( 0.2f, 40 ); }
}
}
}
public class Material
{
private int Cost;
private float Value;
Material( MaterialQualityInfo quality )
{
Cost = quality.Cost;
Value = quality.Value;
}
}
IMHO, this isn't a good usage of static classes. You should use regular object-oriented programming to solve the issue.
I see that all material qualities have 2 properties in common: Value and Cost. For me, this means that you should design a class called MaterialQuality:
public class MaterialQuality
{
public float Value { get; set; }
public int Cost { get; set; }
}
If material qualities are part of an application configuration, I see that you should design a Configuration class as follows:
public class Configuration
{
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
...and if you want to initialize a configuration per application life-cycle, you can improve Configuration class using static field initializers:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
public static Configuration Current => _current;
public List<MaterialQuality> MaterialQualities { get; } = new List<MaterialQuality>();
}
Now adding new material qualities to current configuration is as easy as the following code:
Configuration.Current.MaterialQualities.Add(new MaterialQualities { Value = 0.1f, Cost = 10 });
If you want to provide a fluent API to add material qualities is also easy: we're going to turn public MaterialQualities properties into an ImmutableList<T> (so you force developers to add materials using the method to do so) and add an AddMaterial method:
public class Configuration
{
private readonly static Configuration _current = new Configuration();
private readonly List<MaterialQuality> _materialQualities = new List<MaterialQuality>();
public static Configuration Current => _current;
public IImmutableList<MaterialQuality> MaterialQualities => _materialQualities.ToImmutableList();
public Configuration AddMaterial(float value, int cost)
{
_materialQualities.Add(new MaterialQuality { Value = value, Cost = cost });
return this;
}
}
...and now adding many materials would look even nicer!
Configuration.Current.AddMaterial(0.1f, 10)
.AddMaterial(0.2f, 20)
.AddMaterial(0.2f, 40);
How about:
public enum MaterialQuality
{
Low, Medium, High
}
public class Material
{
private int Cost;
private float Value;
private readonly Dictionary<MaterialQuality, Tuple<int, float>> storageMap = new Dictionary<MaterialQuality, Tuple<int, float>>
{
{ MaterialQuality.Low, Tuple.Create(10, 0.1f)},
{ MaterialQuality.Low, Tuple.Create(20, 0.2f)},
{ MaterialQuality.Low, Tuple.Create(40, 0.2f)},
};
public Material(MaterialQuality quality)
{
Cost = storageMap[quality].Item1;
Value = storageMap[quality].Item2;
}
}
If you are not using your enum widely, you could do something like:
public class Material
{
public float Value { get; private set; }
public int Cost { get; private set; }
public Material(float value, int cost)
{
Value = value;
Cost = cost;
}
public static Material Low { get { return new Material(0.1f, 10); } }
public static Material Medium { get { return new Material(0.2f, 20); } }
public static Material High { get { return new Material(0.2f, 40); } }
}
And then:
var myLowMaterial = Material.Low;
var myMediumMaterial = Material.Medium;
var myHighMaterial = Material.High;
Unless you are using your enum for something, in which case you could add:
public static Material Get(MaterialQuality quality)
{
switch(quality)
{
case MaterialQuality.Low:
return Low;
case MaterialQuality.Medium:
return Medium;
case MaterialQuality.High:
return High;
}
throw new Exception("We should never go here");
}
I was doing some reading here about creating immutable object in java and I was wondering, is it okay to create a mutable object in certain situations?
For example, let's say we were creating a ping-pong game in C#, obviously, we would have a class that represents a ball, and the two paddles, would you write the ball class like this:
class Ball
{
private readonly int xPosition;
private readonly int yPosition;
private readonly int ballSize;
private readonly string ballColor;
public Ball(int x, int y, int size, string color)
{
this.xPosition=x;
this.yPosition=y;
this.ballSize = size;
this.ballColor = color;
}
public int getX
{
get
{
return this.xPosition;
}
}
//left out rest of implementation.
or like this:
class Ball
{
private int xPosition;
private int yPosition;
private int ballSize;
private string ballColor;
public Ball(int x, int y, int size, string color)
{
this.xPosition=x;
this.yPosition=y;
this.ballSize = size;
this.ballColor = color;
}
public int getX
{
get
{
return this.xPosition;
}
set
{
this.xPosition = value;
}
}
}
}
In a situation where our object(ball) can change position, size(smaller or larger depending on level) and color, wouldn't it be better to provide a setter property? In this case making it mutable makes sense? How would you approach this?
If you are using c#, you do not need to go thru the overhead of creating separate fields to make objects immutable. Instead you can do something like this -
class Ball
{
public Ball ( int x, int y, int size, string color)
{ ... }
public int XPos {get; private set; }
public int YPos {get; private set; }
public int Size {get; private set; }
public string BallColor {get; private set; }
}
This way, you can still write methods in the class to mutate the properties but nothing outside of the class can change their values.
I have a class created:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
}
As you can see, it's a very simple class at the moment. My question is, is there a way to create another class inside this so when I call my function I can have a math equation returned?
Example:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.Str.Mod);
The output to the window would be "7"
(Mod is: Math.Floor(Str / 2);)
I have been trying to search both SO and Google for some time and have yet to figure this out. I may be searching for the wrong phrases or this might not even be possible.
Thanks
only way that I can quickly think is Extension Methods
class Program
{
static void Main(string[] args)
{
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
Console.WriteLine(c.Str.Mod());
Console.Read();
}
}
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
}
public static class Ext
{
public static int Mod(this int value)
{
return (int)Math.Floor(value / 2.0);
}
}
public class Character // C should be uppercase here.
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public double ModMe()
{
return Math.Floor(this.Str / 2); // Math.Floor returns double
}
}
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.ModMe());
or:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public int StrMod{
get{
return (int)Math.Floor(Str / 2);
}
}
}
used with:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = 15;
MessageBox.Show(c.StrMod);
Yes, you can create a method called Mod that will do your math for you. It'd look something like this:
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public double Mod(int stat)
{
return Math.Floor(stat/2);
}
}
Create an interface. Use properties. Use descriptive variable names:
public interface ICharacter
{
public string Name { get; }
public int Strength { get; }
}
Then implement it:
public class Character : ICharacter
{
public string Name { get; private set; }
public int Strength { get; private set; }
public Character(string name, int strength)
{
this.Name = name;
this.Strength = strength;
}
}
Now for your question, you should let one class do one thing. So now you can create and initialize a calculator for a character's damage modifier (or whatever "Mod" means):
public class DamageModifierCalculator
{
public int Calculate(ICharacter character)
{
return (int)Math.Floor(character.Strength / 2);
}
}
Now initialize and call it:
var character = new Character("Goofy", 15);
var calculator = new DamageModifierCalculator();
int mod = calculator.Calculate(character);
It's extensible, it's testable and its concerns are separated. You will want to create an interface for the calculator too, as you'll need more of them, preferably one for each kind of calculation.
Or you can just stick it in your Character class, but then it's got nothing to do with OO anymore.
Rather than using Int fields for your stats (at least for your example), make a Stat class, like so:
public class character
{
public string Name, Owner;
public int AC, Speed, maxHP, currHP, AP, SV, Surges;
public Stat Str { get; set; }
public Stat Con { get; set; }
public Stat Dex { get; set; }
public Stat Int { get; set; }
public Stat Wis { get; set; }
public Stat Cha { get; set; }
public class Stat
{
public Stat(int stat)
{
Value = stat;
}
public int Value { get; set; }
public int Mod { get { /*Calcuate Mod from Value.*/; } }
}
}
And call it like this:
character c = new character();
c.Name = "Goofy";
c.Owner = "Me";
c.Str = new Stat(7);
MessageBox.Show(c.Str.Value); //The Value
MessageBox.Show(c.Str.Mod); //The Mod of Strength
For this operation, you can just do :
int x = (int)15 / 2;
Also, you can create nested class, that is to say, a class inside a class.
For example, you would have inside your class something like :
public class MathOperator
{
public int Mod(int x)
{
return (int)x/2;
}
}
And then, just create an instance of this nested class in your class, and use it on c.Str
If Mod is a operation that could apply to any integer, you could define it as an extension method.
static class ExtendInt
{
static public int Mod(this int stat)
{
return stat / 2;
}
}
class UseExtendedInt
{
void UseIt()
{
int a = 1;
int b = a.Mod();
}
}
If you put ExtendInt inside a unique namespace, you can use that namespace only in the files where you want this to work, but otherwise this will be an available function for all integers in that namespace.
If this needs different operations depending on the variable name, you'll have to somehow incorporate reflection or define an enum that identifies the calculation type to pass into Mod.
In most cases, if the calculation types are different, you're better off defining properties like strMod, conMod, etc...
To use that exact syntax, you would need Str to be a different type. One that can be converted from an int and have a property named Mod:
public class character {
// A type that is convertible from int and has a Mod property
public class Modder {
//private variable to hold the integer value
private int _value;
// private constructor that is used by the converter
private Modder(int value){ _value = value; }
// implicit converter to handle the conversion from int
public static implicit operator Modder(int value) {
return new Modder(value);
}
// Property Mod that does the calculation
public int Mod {
get { return _value / 2; }
}
}
public string Name, Owner;
public int Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public Modder Str;
}
I put that class insde the character class, but it doesn't have to be.
public class character
{
public string Name, Owner;
public int Str, Con, Dex, Int, Wis, Cha, AC, Speed, maxHP, currHP, AP, SV, Surges;
public int MathFunction(int input)
{
return (int)(input/2);
}
}
now you can use
MessageBox.Show(c.MathFunction(c.Str));
I have a base class that does calculations on image sizes. I'm deriving a class from that and have predefined image sizes that will be used in my code. While what I have works, I have a strong feeling that I'm not doing it properly.
Ideally, I'd like to just pass DerviedClass.PreviewSize as the parameter to GetWidth without having to create an instance of it.
class Program
{
static void Main(string[] args)
{
ProfilePics d = new ProfilePics();
Guid UserId = Guid.NewGuid();
ProfilePics.Preview PreviewSize = new ProfilePics.Preview();
d.Save(UserId, PreviewSize);
}
}
class ProfilePicsBase
{
public interface ISize
{
int Width { get; }
int Height { get; }
}
public void Save(Guid UserId, ISize Size)
{
string PicPath = GetTempPath(UserId);
Media.ResizeImage(PicPath, Size.Width, Size.Height);
}
}
class ProfilePics : ProfilePicsBase
{
public class Preview : ISize
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
}
}
It seems to me that you want a more flexible implementation of ISize - having an implementation which always returns the same value seems fairly pointless. On the other hand, I can see that you want an easy way of getting the size that you always use for a preview. I would do it like this:
// Immutable implementation of ISize
public class FixedSize : ISize
{
public static readonly FixedSize Preview = new FixedSize(200, 160);
private readonly int width;
private readonly int height;
public int Width { get { return width; } }
public int Height { get { return height; } }
public FixedSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
You could then write:
ProfilePics d = new ProfilePics();
Guid userId = Guid.NewGuid();
d.Save(userId, FixedSize.Preview);
This would reuse the same instance of FixedSize whenever you called it.
There are a few ways that you could do this, depending on your needs. I would look at doing a different interface, setup. Something like this.
public interface ISizedPics
{
int Width {get; }
int Height {get; }
void Save(Guid userId)
}
public class ProfilePics, iSizedPics
{
public int Width { get { return 200; } }
public int Height { get { return 160; } }
public void Save(Guid UserId)
{
//Do your save here
}
}
Then, with this done, you could actually work with it like this.
ISizedPics picInstance = new ProfilePics;
Guid myId = Guid.NewGuid();
picInstance.Save(myId);
This is just one way of doing it, I like this way, as you can easily create a factory class around this that helps you declare the instances as needed.