Assume we have a huge list of numeric cartesian coordinates (5;3)(1;-9) etc. To represent a point in oop I created a struct/object (c#):
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
// Check if x,y falls within certain boundaries (ex. -1000, 1000)
}
}
It might be wrong of how I am using struct. I guess normally you would not use a constructor but this is not the point.
Suppose I want to add a list of 1000 points and there is no guarantee that these coordinates fall within boundaries. Simply if the point is not valid, move to the next one without failing and inform user about it. As for object, I would think that Point should be responsible for instantiation and validation by itself but I am not sure how to deal with it in this particular case. Checking x, y beforehand by the caller would be the simplest approach but it does not feel right because caller would have to handle logic that should reside in Point.
What would the most appropriate approach to validate and handle incorrect coordinates without failing and violating SRP?
You can't do this in the constructor; the constructor either runs succesfully or it doesn't. If it doesn't its because an exception is raised, so, so much for silently failing. You could catch exceptions but that woul basically mean you are using exceptions as a control flow mechanism and that is a big no no, don't do that!
One solution similar to what you are thinking is to use a static factory method:
public struct Point
{
public static bool TryCreatePoint(int x, int y, Bounds bounds, out Point point)
{
if (x and y are inside bounds)
{
point = new Point(x, y);
return true;
}
point = default(Point);
return false;
}
//...
}
And the code adding points to the list should act based upon creation success.
Fun fact: if you are using C# 7 the code could look a lot cleaner:
public static (bool Succesful, Point NewPoint) TryCreatePoint(int x, int y, Bounds bounds)
{
if (x and y are inside bounds)
return (true, new Point(x, y));
return (false, default(Point));
}
I can think of three options:
Have the constructor throw an exception that you catch. This is not really great if you are expecting a lot of failures.
Have an IsValid property on the struct that you can use to filter it out once created.
Have the thing loading the data take responsibility for validating the data as well. This would be my preferred option. You say "it does not feel right because caller would have to handle logic that should reside in Point" but I would argue that the responsibility for checking that loaded data is correct is with the thing loading the data, not the data type. You could also have it throw an ArgumentOutOfRangeException in the constructor if the inputs are not valid now that you are no longer expecting anything invalid to be passed as a belt and bracers approach to things.
What you want to do is simply not posible, an instance of a class is either fully created or not at all. If the constructor has been called the only way to not instantiate an instance is by throwing an exception.
So you have these two opportunities to do this:
Extract a method Validate that returns a bool and can be called from the caller of your class.
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
}
}
public bool Validate() { return -1000 <= X && X <= 1000 && -1000 <= Y and Y <= 1000; }
Of course you could do the same using a property.
Throw an exception in the constructor
public Point(int x, int y)
{
if(x > 1000) throw new ArgumentException("Value must be smaller 1000");
// ...
}
However the best solution IMHO is to validate the input before you even think about creating a point, that is check the arguments passed to the constructor beforehand:
if(...)
p = new Point(x, y);
else
...
To be honest, Point shouldn't check boundaries, so the caller should do that. A point is valid in the range that their X and Y can operate (int.MinValue and int.MaxValue). So a -1000000,2000000 is a valid point. The problem is that this point isn't valid for YOUR application, so YOUR application (the caller), the one who is using point, should have that logic, not inside the point constructor.
Structs in C# are funny so I'll add another "funny" way to check:
struct Point
{
int _x;
public int X
{
get { return _x; }
set { _x = value; ForceValidate(); }
} // simple getter & setter for X
int _y;
public int Y
{
get { return _y; }
set { _y = value; ForceValidate(); }
} // simple getter & setter for Y
void ForceValidate()
{
const MAX = 1000;
const MIN = -1000;
if(this.X >= MIN && this.X <= MAX && this.Y >= MIN && this.Y <= MAX)
{
return;
}
this = default(Point); // Yes you can reasign "this" in structs using C#
}
}
Related
I have a problem to find all possible paths.
a a a b
b a a a
a b b a
Traveling from starting point at 0,0 to end point at 2,3.
I need to get all possible paths.
Possible moves that I can do are moving down and moving right.
Let me tell you where I am stuck.
I am trying to do with a recursive function . Starting with point at 0,0 and moving towards right whenever I can and moving down only when I must.
My recursive function :
public static move(int i,int j)
{
if(possible(x,y+1))
{
move(x,y+1);
move(x+1,y);
}
}
public static bool possible(int i,int j)
{
if((i >=0 && i<3 ) && (j>=0 && j<4))
return true;
else
return false;
}
Not sure about my recursive move function. Still need to expand it . I am not getting exactly how I should implement .
I am able to traverse upto the corner node using that move method but I need that function to retrace back whenever all possible moves from the corner top right point(0,4) is reached.
You need to stop and take a big step back.
The first step should be coming up with the signature of the method. What is the problem statement?
Find all possible paths
Not mentioned: starting from a particular coordinate.
So the method needs to return a set of paths:
static Set<Path> AllPaths(Coordinate start) { /* a miracle happens */ }
OK, now we're getting somewhere; now it is clear what we need. We need a set of things, and we need a path, and we need coordinates.
What's a coordinate? a pair of integers:
struct Coordinate
{
public int X { get; }
public int Y { get; }
public Coordinate(int x, int y) : this()
{
this.X = x;
this.Y = y;
}
}
Done. So pop the stack; what is a path? A path can be empty, or it can be a first step followed by a path:
sealed class Path
{
private Path() { }
private Path(Coordinate first, Path rest)
{
this.first = first;
this.rest = rest;
}
public static readonly Path Empty = new Path();
private Coordinate first;
private Path rest;
public bool IsEmpty => this == Empty;
public Coordinate First
{
get
{
if (this.IsEmpty) throw new Exception("empty!");
return first;
}
}
public Path Rest
{
get
{
if (this.IsEmpty) throw new Exception("empty!");
return rest;
}
}
public Path Append(Coordinate c) => new Path(c, this);
public IEnumerable<Coordinate> Coordinates()
{
var current = this;
while(!current.IsEmpty)
{
yield return current;
current = current.Rest;
}
}
}
Done.
Now you implement Set<T>. You will need to have the operations "all items" and "union this set with another to produce a third". Make sure that sets are immutable. You don't want to change a set when you add new items to it; you want a different set. The same way you don't change 3 into 4 when you add 1; 3 and 4 are different numbers.
Now you have all the tools you need to actually solve the problem; now you can implement
static Set<Path> AllPaths(Coordinate start)
{
/* a miracle happens */
}
So how does this work? Remember that all recursive functions have the same form:
Solve the trivial case
If we're not in a trivial case, reduce the problem to a smaller case, solve it recursively, and combine solutions.
So what is the trivial case?
static Set<Path> AllPaths(Coordinate start)
{
/* Trivial case: if the start coordinate is at the end already
then the set consists of one empty path. */
Implement that.
And what is the recursive case?
/* Recursive case: if we're not at the end then either we can go
right, go down, or both. Solve the problem recursively for
right and / or down, union the results together, and add the
current coordinate to the top of each path, and return the
resulting set. */
Implement that.
The lessons here are:
Make a list of all the nouns in the problem: set, path, coordinate, and so on.
Make a type that represents each one. Keep it simple, and make sure you implement exactly the operations each type needs.
Now that you have an abstraction implemented for each noun you can start designing algorithms that use the abstractions, with confidence that they will work.
Remember the basic rules of recursion: solve the base case if you can; if not, solve the smaller recursive cases and combine the solutions.
public void MoveUp(Object sender, MoveEventArgs e)
{
if (CanMoveUp(e.CurrentPosition.Y)) ...
}
public void MoveDown(Object sender, MoveEventArgs e)
{
if (CanMoveDown(e.CurrentPosition.Y)) ...
}
public void MoveLeft(Object sender, MoveEventArgs e)
{
if (CanMoveLeft(e.CurrentPosition.X)) ...
}
public void MoveRight(Object sender, MoveEventArgs e)
{
if (CanMoveRight(e.CurrentPosition.X)) ...
}
private bool CanMoveUp(double y) => (y - 1) > 0;
private bool CanMoveDown(double y) => (y + 1) < 4;
private bool CanMoveLeft(double x) => (x - 1) > 0;
private bool CanMoveRight(double x) => (x + 1) < 4;
These Values may not be right, but the code is reusable and easily maintainable in the event you would want to add any other possible barriers to movement you could easily add the additions to each method.
It's hard not to give away the farm and be helpful. You should break down the decision logic to 3 boundary functions
inBoundsX x
// return true if x is in bounds, false otherwise
inBoundsY y
// return true if y is in bounds, false otherwise
inBoundsXY x,y
// return true if x and y are in bounds, false otherwise
Your recursive function should always validate the initial state it's given, then decide which way to move next.
move x,y
if inBoundsXY x,y
print I am here x,y
// use InboundsX, InboundsY to decide next move.
I am building an app that lets me control my Android devices from my PC. It's running great so now I want to start cleaning up my code for release. I'm trying to clean up solution references that I don't need so I took a look at the using System.Drawing; that I have for implementing the Point class. The thing is, I don't really need it if I switch to using a two-dimensional Int32 array.
So I could have: new Int32[,] {{200, 300}}; instead of new Point(200, 300); and get rid of the System.Drawing namespace altogether. The question is: does it really matter? Am I realistically introducing bloat in my app by keeping the System.Drawing namespace? Is Int32[,] meaningfully more lightweight?
Or, should I not use either and just keep track of the x,y coordinates in individual Int32 variables?
EDIT: I got rid of the original idea I wrote: Int32[200, 300] and replaced it with new Int32[,] {{200, 300}}; because as #Martin Mulder pointed out Int32[200, 300] "creates a two-dimensional array with 60000 integers, all of them are 0."
EDIT2: So I'm dumb. First of all I was trying to fancify too much by using the multi-dimensional array. Utter, overboard silliness. Secondly, I took the advice to use a struct and it all worked flawlessly, so thank you to the first four answers; every one of them was correct. But, after all that, I couldn't end up removing the System.Drawing reference because I was working on a WinForms app and the System.Drawing is being used all over in the designer of the app! I suppose I could further refactor it but I got the size down to 13KB so it's good enough. Thank you all!
Just create your own:
public struct Point : IEquatable<Point>
{
private int _x;
private int _y;
public int X
{
get { return _x; }
set { _x = value; }
}
public int Y
{
get { return _y; }
set { _y = value; }
}
public Point(int x, int y)
{
_x = x;
_y = y;
}
public bool Equals(Point other)
{
return X == other.X && Y == other.Y;
}
public override bool Equals(object other)
{
return other is Point && Equals((Point)other);
}
public int GetHashCode()
{
return unchecked(X * 1021 + Y);
}
}
Better yet, make it immutable (make the fields readonly and remove the setters), though if you'd depended on the mutability of the two options you consider in your question then that'll require more of a change to how you do things. But really, immutability is the way to go here.
You are suggesting very ill advised:.
new Point(200, 300) creates a new point with two integers: The X and Y property with values 200 and 300.
new Int32[200,300] creates a two-dimensional array with 60000 integers, all of them are 0.
(After your edit) new Int32[,] {{200, 300}} also creates a two-dimensional array, this time with 2 integers. To retrieve the first value (200), you can access it like this: array[0,0] and the second value (300) like array[0,1]. The second dimension is not required or needed or desired.
If you want to get rid of the reference to the library there are a few other suggestions:
new Int32[] {200, 300} creates an one-dimensional array of two integers with values 200 and 300. You can access them with array[0] and array[1].
As Ron Beyer suggested, you could use Tuple<int, int>.
Create your own Point-struct (pointed out by Jon Hanna). It makes your applicatie a bit larger, but you prevent the reference and you prevent the library System.Drawing is loaded into memory.
If I wanted to remove that reference, I would go for the last option since it is more clear to what I am doing (a Point is more readable than an Int32-array or Tuple). Solution 2 and 3 are slightly faster that solution 1.
Nothing gets "embedded" in your application by just referencing a library. However, if the Point class really is all you need, you could just remove the reference and implement you own Point struct. That may be more intuitive to read instead of an int array.
Int32[,] is something different by the way. It's a two-dimensional array, not a pair of two int values. You'll be making things worse by using that.
You could use Tuple<int, int>, but I'd go for creating your own structure.
As some people have suggested implementations here. So just wrap your two integers, I'd just use this:
public class MyPoint
{
public int X;
public int Y;
}
Add all other features only if needed.
As #Glorin Oakenfoot said, you should implement your own Point class. Here's an example:
public class MyPoint // Give it a unique name to avoid collisions
{
public int X { get; set; }
public int Y { get; set; }
public MyPoint() {} // Default constructor allows you to use object initialization.
public MyPoint(int x, int y) { X = x, Y = y }
}
Just wondering cause I often find myself giving input like coordinates (X, Y) and was wondering which case is better.
If I store 3 int in one array I have a reduction of the code to 1/3, but are there more reason to prefer array over multiple vars?
Example to clarify:
int[] coord = new int[2];
coord[0] = 3;
coord[1] = 2;
or
int x = 3;
int y = 2;
I'd say that if the coordinates are so tightly coupled that you always pass both of them together (which I believe to be true), you can create a struct to encapsulate them.
public struct Coords
{
private int x;
private int y;
public Coords(int x, int y)
{
this.x = x;
this.y = y;
}
public int X
{
get { return x; }
}
public int Y
{
get { return y; }
}
}
In such scenario you can pass it like this:
var c = new Coords(1, 2);
MyMethod(c);
You have an optimization tag attached to your question, but if the problem is not critical to your application's performance, I'd go with readability/design over nanoseconds.
It kinda depens on what you're using the values for.
If you're holding a ton of values, like in a game, you should make it easily readable for yourself and maybe other coders and clarify what a value means.
You shouldn't hold many values in one array, like say HP, MP, speed, rotation, height, width,... and not clarifying what they are.
But you should say HP=100; MP=80, ...
In cases like this, there's almost everytime a 'player' class though.
That class contains player.hitpoints, player.magicpoints, player.speed, ...
But for coordinates, what I think programmers use is an array with x, y (and sometime z) coordinates.
Does the order in which I set properties using the object initializer syntax get executed in the exact same order?
For instance if I do this:
var s = new Person { FirstName = "Micah",
LastName = "Martin",
IsLoaded = true
}
will each property get set in the same order?
Yes.
Apologies for getting interrupted (I have to actually do some work every so often). The spec doesn't explicitly say it, but it makes it pretty clear IMO in section 7.6.10.2:
An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas.
(Note the word "sequence" here, rather than "set". I personally think that's significant, as a sequence is ordered.)
The following class represents a point with two coordinates:
public class Point
{
int x, y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}
An instance of Point can be created and initialized as follows:
Point a = new Point { X = 0, Y = 1 };
which has the same effect as
Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;
where __a is an otherwise invisible and inaccessible temporary variable.
EDIT: I've had a response from Mads Torgersen, who has basically said that anything which can be done now will preserve the order. There may be some oddities in future where the order is not preserved in weird cases where you're doing something other than setting a property/field, but that will depend on where the language goes.
It's worth pointing out that there are actually lots of steps going on here - there's the order of execution of the evaluation of the arguments (i.e. the RHS bits) and the order of execution of the assignments. For example, if you have:
new Foo
{
A = X,
B = Y
}
all the following orders are possible while still maintaining the order of the actual property execution (A and B):
Evaluate X, assign to A, evaluate Y, assign to B
Evaluate X, evaluate Y, assign to A, assign to B
Evaluate Y, evaluate X, assign to A, assign to B
I believe the first option is the one actually taken, but this was just to demonstrate that there's more to it than meets the eye.
I would also be very wary of actually writing code which depends on this...
Does the order in which I set properties using the object initializer syntax get executed in the exact same order?
For instance if I do this:
var s = new Person { FirstName = "Micah",
LastName = "Martin",
IsLoaded = true
}
will each property get set in the same order?
Yes.
Apologies for getting interrupted (I have to actually do some work every so often). The spec doesn't explicitly say it, but it makes it pretty clear IMO in section 7.6.10.2:
An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas.
(Note the word "sequence" here, rather than "set". I personally think that's significant, as a sequence is ordered.)
The following class represents a point with two coordinates:
public class Point
{
int x, y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}
An instance of Point can be created and initialized as follows:
Point a = new Point { X = 0, Y = 1 };
which has the same effect as
Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;
where __a is an otherwise invisible and inaccessible temporary variable.
EDIT: I've had a response from Mads Torgersen, who has basically said that anything which can be done now will preserve the order. There may be some oddities in future where the order is not preserved in weird cases where you're doing something other than setting a property/field, but that will depend on where the language goes.
It's worth pointing out that there are actually lots of steps going on here - there's the order of execution of the evaluation of the arguments (i.e. the RHS bits) and the order of execution of the assignments. For example, if you have:
new Foo
{
A = X,
B = Y
}
all the following orders are possible while still maintaining the order of the actual property execution (A and B):
Evaluate X, assign to A, evaluate Y, assign to B
Evaluate X, evaluate Y, assign to A, assign to B
Evaluate Y, evaluate X, assign to A, assign to B
I believe the first option is the one actually taken, but this was just to demonstrate that there's more to it than meets the eye.
I would also be very wary of actually writing code which depends on this...