Define maximum and minimum for fields in struct - c#

I have a struct and an integer variable on it. My variable value must be between 1200 and 1599. but in default constructor I have no control in value of variable. How can I do this in my struct?
struct MyStruct
{
public int x;
public MyStruct(int x)
{
if(x>1599)
this.x=1599;
else if(x<1200)
this.x=1200;
else
this.x=x;
}
}

Another variant on using a property and a private backing field:
struct MyStruct
{
private int x;
public MyStruct(int x)
{
if (x > 1599)
this.x = 399;
else if (x < 1200)
this.x = 0;
else
this.x = x - 1200;
}
public int X { get { return x+1200; } }
}
Which ensures that the default constructed value is "in range".
But any variant is going to introduce some overhead, so it's up to you whether this is acceptable.

Use a property with a backing field:
struct MyStruct
{
private const int MIN_VALUE = 1200;
private const int MAX_VALUE = 1599;
private int x;
public int X
{
get { return x + MIN_VALUE; }
set
{
if(value > MAX_VALUE)
x = MAX_VALUE;
else if(value < MIN_VALUE)
x = MIN_VALUE;
else
x = value;
x -= MIN_VALUE;
}
}
// constructor is not really needed anymore, but can still be added
}
I combined the property with my setter and Damien_The_Unbeliever's getter to get the initial state of x right. I also agree with Tim about constants for the "magic numbers" and added that too. So please give this two also credit for "my answer".
Also as DatVM already said: Public fields/properties should start with a capital letter according to the common C# naming guidlines. This also enalbes you to use the same name for the backing field, but starting with a small letter (I personally do NOT like the ugly _)...
And last but not least: Please read rexcfnghk's answer, even if it is not really an answer, as he is also absolutely correct.

My variable value must be between 1200 and 1599
In C#, you cannot define your own default constructor for structs. If you have an array of MyStruct, like var myArray = new MyStruct[5], the default constructor of MyStruct will be invoked and elements in myArray will have all have x equals to 0, which is invalid according to your requirement.
Which is why I believe you have an incorrectly designed struct. According to the Framework Design Guidelines
√ DO ensure that a state where all instance data is set to zero, false, or null (as appropriate) is valid.
This prevents accidental creation of invalid instances when an array of the structs is created.
If you need argument validation when your struct's default constructor is invoked, use a class instead.
Also, your current design of MyStruct makes it mutable. please take a look on why Mutable structs are evil.

I would use properties with getter and setter and a private backing field where you can implement this logic or even throw an ArgumentOutOfRangeException if the value is outside of the boundaries.
Here is an example:
struct MyStruct
{
private const int MIN_VALUE = 1200;
private const int MAX_VALUE = 1599;
private int _X;
public int X
{
get { return _X; }
set { _X = checkBoundaries(value); }
}
private static int checkBoundaries(int x)
{
if (x > MAX_VALUE)
return MAX_VALUE;
else if (x < MIN_VALUE)
return MIN_VALUE;
else
return x;
}
public MyStruct(int x)
{
_X = checkBoundaries(x);
}
}
It's good practices to always use properties even if you don't need to restrict the access in the first place. Then it's easier to implement such a logic if you need.
One final note: i would suggest to use a class instead of struct.
You cannot define a default constructor in a struct, so you cannot prevent _X from being initialized with the default value 0.
You cannot initialze _X with the minimum value inline since that is also not allowed in structs
If your types are getting more comlex and you have rules like this it's a good indicator that a class would be more appropriate

You should change x into property instead:
private int _x;
public int x {
get
{
return _x;
}
set
{
_x = value;
if (_x > 1599)
{
_x = 1599
}
else if (_x < 1200)
{
_x = 1200
}
}
}
P.S: as for C# naming convention, it should be called X (capital) instead of x

A struct can be made to have a default value if, rather than using a public field, one uses a private field and a public property which transforms the field's value in such a way that its default value will map to the desired default for the structure. For example, you could have a backing field int _x_minus_1200; and have a property getter which returns _x_minus_1200 + 1200. I'm not hugely keen on such approaches (generally I prefer for structures to have public fields and behave like structures, and have the meaning and validation of structure fields be a function of the code that uses the structures) but in some cases they can be helpful.

Related

How to control the maximum value of variables?

As the title says, I would like to set the maximum value of the skill, stam and luck integers to the value of the related *Max integers. The *Max int values are set randomly during the start up of the program and the regular values are changed throughout the running of the program. There may be a few instances where the *Max value gets increased or decreased during play.
public static int skillMax = 0;
public static int stamMax = 0;
public static int luckMax = 0;
public static int skill = skillMax;
public static int stam = stamMax;
public static int luck = luckMax;
As my knowledge of C# is still in its infancy, I have not tried much. However I have searched far and wide on the internet however and not been able to find anything except for the MinValue and MaxValue fields and this piece of code with no explanation:
protected int m_cans;
public int Cans
{
get { return m_cans; }
set {
m_cans = Math.Min(value, 10);
}
}
Thanks in advance for any advice you throw my way!
Explanation for the code: Cans is a property. Properties provide controlled access to class or struct fields (variables). They consist of two methods called get to return a value and set to assign the value. A property can also have only a getter or only a setter.
The property Cans stores its value in a so called backing field. Here m_cans. The setter gets the new value through the keyword value.
Math.Min(value, 10) returns the minimum of the two parameters. I.e., for example, if value is 8, then 8 is assigned to m_cans. If value is 12, then 10 is assigned to m_cans.
You can use this property like this
var obj = new MyCalss(); // Replace by your real class or struct name.
obj.Cans = 20; // Calls the setter with `value` = 20.
int x = obj.Cans; // Calls the getter and returns 10;
Properties help to implement the principle of Information hiding.
You can easily adapt this example your variables. Often class level variables (fields) are prepended with _ to differentiate them from local variables, i.e. variables declared in methods. Properties are written in PascalCase.
private static int _skillMax; // Fields are automatically initialized to the default
// value of their type. For `int` this is `0`.
public static int SkillMax
{
get { return _skillMax; }
set {
_skillMax = value;
_skill = _skillMax; // Automatically initializes the initial value of Skill.
// At program start up you only need to set `SkillMax`.
}
}
private static int _skill;
public static int Skill
{
get { return _skill; }
set { _skill = Math.Min(value, _skillMax); }
}
Create methods to update values
private static void UpdateSkill(int newValue)
{
skill = newValue;
skillMax = newValue > skillMax ? newValue : skillMax;
}

how do i use a property { get; }?

I noticed that in the Microsoft.Xna.Framework.Rectangle struct, there are plenty of properties that are just public int Bottom { get; } or public Point Center { get; }. I, for the life of me, can't figure out what's going on here. I've tried replicating this in some of my own structs, but I can't figure out how to give it a value in the first place without the set; keyword. What is it that the Rectangle struct is doing to {get;}?
The reason why the Rectangle.Bottom doesn't have a set is because it is a calculated value, Top + Height. If you would set that, what would you like to happen? Change the y position? Change the height? It is impossible to know. So you have to decide yourself and change the Top or Height based on what you actually want.
The idea of properties is not just to have a variable and set or get it. If it was we could just use public variables and that's it. Rather the idea is to allow validation and calculated properties.
public int Bottom
{
get { return Top + Height; }
}
As you can see, there is no need to set it to anything, since it will infer its value based on other values.
(Of course internally it will most likely not use the other properties, but rather the actual variables due to performance)
It means the underlying value that the property gives you access to cannot be set later on.. you can only "get" the underlying value.
When you instantiate a Rectangle, you have to pass it a few values:
public Rectangle (int x, int y, int width, int height)
My guess (without looking at the source code) is that the property values (Center, Bottom, etc) are all set in the constructor. You can't alter them later on.. either look for another property to set (i.e. X or Y), or create a new Rectangle based on the existing one.
var newRect = new Rectangle(oldRect.X, oldRect.Y, oldRect.Width, oldRect.Height);
For comparison, here's a portion of the source code from the System.Drawing.Rectangle struct, which is probably fairly close to what you're dealing with. Notice that you can set certain values via the constructor, which are then stored in private variables, and are accessible (but only changeable in some) properties.
public struct Rectangle
{
public static readonly Rectangle Empty = new Rectangle();
private int x;
private int y;
private int width;
private int height;
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int X
{
get { return x; }
set { x = value; }
}
public int Left
{
get { return X; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public int Top
{
get { return Y; }
}
...
...
}
Consider the following:
private int myVar;
public int MyProperty
{
get { return myVar; }
}
Here you see an example, taken directly from Visual Studio's C# snippets, showing how to implement a get-only property. You need to set the backing field, but it cannot be done via the property because this property is said to be a read-only property or a property with no setter method. The purpose of such properties is to make a contractual statement about your object "this property cannot be set."
This is similar to having a private setter, however, you cannot enforce access modifiers in an interface definition. Therefore, this syntax serves a specific purpose when defining data contracts and object interfaces, and that is to say "this property cannot be set, by contract, and no subclass may expose a public setter as part of this contract."
As an aside, you can circumvent access modifiers using reflection, but this is not the common case (and 99% of the .NET developers out there are probably unaware of this fact.)
Typically backing fields are set via a constructor, via reflection, or as part of object initialization.
This is also core syntax, it forms the basis of modern syntactic sugar. Consider the following property definition:
public int MyProperty { get; set; }
This is entirely syntactic sugar, and not actually valid for a C# 1.0 compiler. Today at compile time a backing field is generated on your behalf. Thus, the following syntax is only valid for interface definitions (as it would never return a meaningful value otherwise.)
public int MyProperty { get; }
The above is an (invalid) attempt to create a read-only property using the newer auto-property syntax.
References:
When should use Readonly and Get only properties
Using a backing variable for getters and setters
Is it possible to access backing fields behind auto-implemented properties?
https://msdn.microsoft.com/en-us/library/bb384054.aspx
https://msdn.microsoft.com/en-us/library/w86s7x04.aspx

Why is this method Impure?

I read this answer: https://stackoverflow.com/a/9928643/16241
But I obviously don't understand it because I can't figure out why my method is impure. (The method in question is ToExactLocation()).
public struct ScreenLocation
{
public ScreenLocation(int x, int y):this()
{
X = x;
Y = y;
}
public int X { get; set; }
public int Y { get; set; }
public ExactLocation ToExactLocation()
{
return new ExactLocation {X = this.X, Y = this.Y};
}
// Other stuff
}
Incase you need it here is the exact location struct:
public struct ExactLocation
{
public double X { get; set; }
public double Y { get; set; }
// Various Operator Overloads, but no constructor
}
And this is how I call it:
someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation == someScreenLocation.ToExactLocation())
{
// Do stuff
}
When I do that, ReSharper flags it with "Impure Method is called for readonly field of value type."
Why is it saying that? And what can I do to make it go away?
It's not pure because it does not return a value dependent only on its input. When the value of X or Y changes so does the return value of ToExactLocation, i.e., its output depends on internal, mutable state.
Additionally, the setters for X or Y in ExactLocation may mutate the input. The getters of ScreenLocation may as well.
someScreenLocation is a readonly field and is a value type. You are calling ToExactLocation on a value, i.e., a readonly field. When you access a reaodnly value type a copy is created as to avoid mutating the value itself. However, your call may mutate that value, which, in many cases, is not what you want as you will be mutating a copy. This is why you get a warning.
In this case, you can ignore it, but I would avoid mutable value types in general.
EDIT:
Let me attempt to simplify...
struct Point
{
int X;
int Y;
bool Mutate() { X++; Y++; }
}
class Foo
{
public readonly Point P;
Foo()
{
P = new Point();
P.Mutate(); // impure function on readonly value type
}
}
When Mutate() is called, a copy of P is created and passed along with the method. Any mutation of P's internal state will be irrelevant as it mutates a copy.
One of the conditions of a Pure Method is that its output (return value) is wholly dependent on its input (arguments).
Your .ToExactLocation() method is not pure, because its output depends both on the input arguments and also on the current value of a mutable struct.
Resharper doesn't like this, because mutable structs are bad (don't use them). I expect the error would go away if you either changed your code to use a class instead of a struct or redesigned the struct so the the .X and .Y members could only be set by the constructor.
Reading the answer, I found out that pure functions are necessarily like functions in mathematics. f(x) = x^2 + 2x + 10 will always return 10 if x is 0.
So ToExactLocation() must return the same values each time it is called, regardless changes to object since initial creation, for it to be called "pure".
There are 2 meaning of "pure function": one theoretical (no side effects/no dependency on mutable state) and another is what ReSharper thinks about functions.
From theoretical point of view your function is not pure because it depends on mutable state. Sample:
var someScreenLocation = new ScreenLocation(1,1);
var locationOne = someScreenLocation.ToExactLocation();
var locationTwo = someScreenLocation.ToExactLocation();
someScreenLocation.X = 3;
var locationThree = someScreenLocation.ToExactLocation();
For method to be pure it can change its result only based on input (not at all as in this case since there is no arguments). But you can clearly observe that locationOne and locationTwo are the same (good sign so far), but unfortunately locationThree is different even if the input (arguments to the function) still the same.
You can make it theoretically pure by making X and Y readonly (and adding constructor).
Even after the change ReSharper will still think it is not pure - to convince it you can use Pure attribute to mark it as pure.
Note that ReSharper marks usage of "impure" functions even in constructor of the class with readonly field. Sample below shows ReSharper warnings:
struct Point
{
public int X;
public int Y;
public Point(int x, int y){X = x;Y = y;}
public void Mutate(){X++;}
public Point TheoreticallyPure(){return new Point(1, 1);}
[Pure] public Point MarkedPure(){ return new Point(1, 1);}
}
class WithReadonlyField
{
public readonly Point P;
public WithReadonlyField()
{
P = new Point();
P.TheoreticallyPure(); // impure function on readonly value type
P.MarkedPure(); // return value of pure not used
P.Mutate(); // impure function on readonly value type - modifies P.
P = new Point().MarkedPure(); // ok to modify P multiple times.
}
public void NormalMethod()
{
P.Mutate(); // impure function on readonly value type, no changes to P
}
}
C# allows modification of readonly fields up to the end of constructor, but ReSharper marks usages of all "impure" functions there too (Note that Mutate function in constructor actually changes value of readonly field P, unlike in NormalMethod where it has no effect).
"readonly... assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class"
Most likely this behavior of ReSharper is for consistency and to avoid cases where moving perfectly valid code changes behavior completely.
It would be better to model this as a static method (on either class) and would get rid of the impure warning. Explanation omitted, as the other answers covers the why already.
Example:
public static ExactLocation ToExactLocation(ScreenLocation loc)
{
return new ExactLocation {X = loc.X, Y = loc.Y};
}
or use an extension method
public static ExactLocation ToExactLocation(this ScreenLocation loc)
{
return new ExactLocation {X = loc.X, Y = loc.Y};
}
Not really sure about the cause, and I'd put this as a comment if it would format correctly...
Wouldn't you want something like:
var someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation.X == someScreenLocation.ToExactLocation().X &&
DestinationLocation.Y == someScreenLocation.ToExactLocation().Y)
{
// Do stuff
}

Meaning of "this" for a struct (C#)

According to MSDN (Section 11.3.6 of the C# spec):
Within an instance constructor of a
struct, this corresponds to an out
parameter of the struct type, and
within an instance function member of
a struct, this corresponds to a ref
parameter of the struct type. In both
cases, this is classified as a
variable, and it is possible to modify
the entire struct for which the
function member was invoked by
assigning to this or by passing this
as a ref or out parameter.
I don't get it. How is this different for a struct than for a class? Code examples are appreciated
Eric Lippert had a fabulous post on mutating readonly structs a while back that will really help clarify the issue for you. There's even a code example, and a quiz!
The salient point is that structs obey value semantics and classes do not and so this must mean something different for the two. this is readonly for a class, but not for a struct. The following code is legal
struct Point {
public int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void DoGoTime() {
GoTime(ref this);
}
public static void GoTime(ref Point p) {
p.x = 100;
p.y = 100;
}
}
but is not if "struct" is replaced by "class."
When you're dealing with structs, you're dealing with value types.
In a class, "this" is a reference to the current instance. This lets you mutate the class instance by setting properties/fields on the class.
However, if you're in a struct, things act differently. When you're in a struct's method, "this" lets you mutate the struct. However, if you're using this in a method, you're almost always dealing with a copy of the "original" struct.
For example:
struct Test
{
int i;
void Mutate() {
this.i += 1;
}
}
When you use this:
void MutateTest(Test instance)
{
instance.Mutate();
}
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(); // test.i is now 4
Console.WriteLine(test.i); // Writes 4
MutateTest(test); // MutateTest works on a copy.. "this" is only part of the copy itself
Console.WriteLine(test.i); // Writes 4 still
}
Now, the stranger part - this is valid, and what that quote was saying:
struct Test
{
public Test(int value)
{
this.i = value;
}
int i;
void Mutate(int newValue) {
this = new Test(newValue); // This wouldn't work with classes
}
}
///
{
Test test = new Test();
test.i = 3;
Console.WriteLine(test.i); // Writes 3
test.Mutate(4);
Console.WriteLine(test.i); // Writes 4
Jason's answer and Eric's post show one aspect of this which is interesting... but there's another which is even more alarming:
You can reassign this within a method, even if the type is otherwise immutable.
To demonstrate it, we'll use a struct which is stored in a non-readonly variable, but which contains a readonly field:
using System;
public struct LooksImmutable
{
private readonly int value;
public int Value { get { return value; } }
public LooksImmutable(int value)
{
this.value = value;
}
public void GoCrazy()
{
this = new LooksImmutable(value + 1);
}
}
public class Test
{
static void Main()
{
LooksImmutable x = new LooksImmutable(5);
Console.WriteLine(x.Value);
x.GoCrazy();
Console.WriteLine(x.Value);
}
}

force get/set access of private variables for private properties

If I have a private variable that I want to have some internal validation on, and I want to keep that validation in one place, I put it behind a getter/setter and only access it thorugh that getter/setter. That's useful when dealing with public properties, because the other code cannot access the private variable, but when I'm dealing with object inside the class itself, is there any way to enforce the getter/setter?
private int _eyeOrientation;
private int eyeOrientation
{
get
{
return _eyeOrientation;
}
set
{
if (value < 0)
{
_eyeOrientation = 0;
}
else
{
_eyeOrientation = value % 360;
}
}
}
The issue here being that the other functions in the class may accidentally modify
_eyeOrientation = -1;
which would throw the program into a tizzy. Is there any way to get that to throw a compiler error?
Sounds like you need a angle type.
// Non mutable Angle class with a normalized, integer angle-value
public struct Angle
{
public Angle(int value)
{
Value = value;
}
private angle;
public Value
{
get { return angle; }
private set { angle = Normalize(value); }
}
public static int Normalize(int value)
{
if (value < 0) return 360 - (value % 360);
return value % 360;
}
}
public class SomeClass
{
public Angle EyeOrientation { get; set; }
}
If you have a certain kind of value, like angles, money, weight or whatever, it is always a good praxis to make it a own type, even if the value itself is stored in a int, decimal etc. This type makes your interfaces clearer and typesafe. It is not the same if you expect an Angle or a integer value as argument of some method.
In general, you shouldn't worry about this. Class members can still use the properties, if you don't want to put the checking in the class itself.
If your class is getting so large that you no longer trust methods inside the class, I'd think that it's time to start refactoring and breaking this into smaller classes that are more easily managable.
You could possibly define it in a nested class.
public class NeedsEye
{
Eye _eye = new Eye();
public NeedsEye()
{
// now, here, any access to the property must be made through the
// _eye variable. The Eye class has access to any of the properties
// and members of the NeedsEye class, but the NeedsEye class has not
// any access to members of the Eye class.
}
private class Eye
{
private int _orientation;
public int Orientation
{
get { return _orientation; }
if (value < 0)
{
_eyeOrientation = 0;
}
else
{
_eyeOrientation = value % 360;
}
}
}
}
You can mark the field as obsolete so that the compiler will generate a warning if you try to access it, and then suppress that warning for the property getter/setter.
The warning codes that you'd need to suppress are CS0612 for the plain Obsolete attribute and CS0618 if the attribute has a custom message.
In general I'd consider this a bit of a hack and try to avoid it if possible. A better solution would be to comment the code appropriately and train your fellow developers so that they'll do the right thing.
[Obsolete("Please use the EyeOrientation property instead.")]
private int _eyeOrientation;
public int EyeOrientation
{
#pragma warning disable 612, 618
get
{
return _eyeOrientation;
}
set
{
_eyeOrientation = (value > 0) ? value % 360 : 0;
}
#pragma warning restore 612, 618
}
Just put your private attribute and public getters/setters into a private class.
Then only the getter and setter can access the private attribute.
It is overkill but would work. :)
Depending on your tools you could look into enforcing a coding convention not allowing direct access to a private member outside a get/set
Might be some more work but you won't have to create a series of wrapper classes.

Categories

Resources