Alternative to if/else on combinational logic in C# - c#

I am working on a program that uses a grid system. The system needs a method that works on every element of the grid, based on the value of its neighbours' elementType. What I currently use is something along the lines of the follows:
enum ElementType{
A,B
}
if (neighbourUp.elemType == ElementType.A && neighbourDown == ElementType.A){
method1();
}
if (neighbourLeft == ElementType.A and current == ElementType.B){
method2();
}
and so on. As you can see this is hard to manage when the types increase. Ideally I would like to use polymorphism here but I feel creating a class for each combination is too much work. Also there may be cases where the method for some combinations is the same.
I would like some advice on how to approach this. Also the ElementType needs to be expandable to accommodate new types that may get added later.

You can use the Strategy Design Pattern which comes under Behavioral Patterns to avoid execution of code base on conditions
You can use these links to know more about strategy design patterns
https://www.dofactory.com/net/strategy-design-pattern
https://www.youtube.com/watch?v=v9ejT8FO-7I

store both of values in array with keys and apply for loop on neighbour and then ElementType, then you can compare using key values until the items in array.

I would define a list of rules and then your main code simply loops around all the cells and then invokes the rules that match for a cell. Then you can add or remove rules relatively easily in the future without changing the main loop logic.
So you need a class that represents a rule, each rule indicates the left/right/up/down types that it matches against and then has a method that is called if the match occurs. Make the matching fields nullable so you can indicate if you do not care what the neighbour type is...
class Rule
{
public ElementType? Left { get; set; }
public ElementType? Right { get; set; }
public ElementType? Top { get; set; }
public ElementType? Bottom { get; set; }
public Action Process { get; set; }
}
...in practice your 'Process' would need at least one parameter, a reference to the cell that is being processed. So you can change it to be Action or whatever.

Related

Is it ok that 2 objects reference each other?

I'm making a chess game in C#. I've got 2 classes, Field and Piece:
public class Field
{
// the piece that is standing on this field
// null if no piece is standing on it
public Piece piece { get; set; }
}
public class Piece
{
// the field this piece is standing on
public Field field { get; set; }
}
When a piece moves, this method is called (in class Piece):
public void Move(Field field)
{
this.field = field;
field.piece = this;
}
This doesn't seem to be good coding, because everytime I change the field property, I also have to change the piece property for that field. I do need both properties though, because elsewhere in my code, I need them both to do checks etc (e.g. what's the field this piece is on and by what piece is this field taken).
My question: is this completely ok, is it a bad code smell or is it totally wrong? What would be a good solution to solve this?
Any advice? Thanks in advance!
The problem I see here is that you have Piece.field and Field.piece as public properties. This means that others can set these properties without updating the corresponding one.
Additionally, when you move a piece from one field to another, you don't remove the piece from the previous field, and we allow pieces to move to occupied squares, which will result in multiple pieces referring to the same field, but the field will only refer to the last piece placed there.
To address these, I would make the properties read only (with a private setter), forcing clients to call the corresponding Set or Move method to change them. Then, in this method, we can verify that the field we're moving to is not occupied (if it is, we simply throw an exception - the client must check this first before calling Move), and that we clear the Piece from the Field we moved from.
The validation work can be done in either the Field or Piece class, or both. I put it all in the Field class to simplify things.
Even still, there are problems with this. You can call Field.SetPiece(piece) directly (instead of Piece.MoveTo(field);), which will leave the piece with a null value for Field. So this is only a slight improvement, but not the ideal solution. See below for a better idea.
public class Field
{
public Piece Piece { get; private set; }
public bool Occupied => Piece != null;
public void ClearPiece()
{
// Remove this field from the piece
if (Piece?.Field == this) Piece.MoveTo(null);
// Remove the piece from this field
Piece = null;
}
public void SetPiece(Piece piece)
{
if (piece != null)
{
if (Occupied)
{
throw new InvalidOperationException(
$"Field is already occupied by {Piece}.");
}
// Remove piece from the piece's previous field
if (piece.Field?.Piece == piece)
{
piece.Field.ClearPiece();
}
}
Piece = piece;
}
}
public class Piece
{
public Field Field { get; private set; }
public void MoveTo(Field field)
{
field.SetPiece(this);
Field = field;
}
}
After thinking a little more about this, I think a better solution would be to have a GameManager class that handles all the validation and movement, and then we can make the Field and Piece classes "dumb".
This makes sense because there is a lot more validation to be done before setting a Piece on a Field. Is it ok to move this piece to the location (i.e. if the King is in check and this doesn't block it, then it's not allowed). Is the Field a valid landing spot for the piece based on the piece's move rules (i.e. a horizontal position for a bishop would not be allowed)? Is there anything blocking the path of the piece to get to the destination? Is the destination occupied by another piece belonging to the same player? Many things to evaluate before moving a piece.
Additionally, this would allow us to reuse the Piece and Field classes in other types of games, which may have a different set of rules, and a different GameManager to enforce them.
No! This relates to concept of circular dependency. Although applied for modules, this may very well be seen as precursor for such.
More concretely, this is an ideal example for mutually recursive objects. Conceptually, if you substitute (semi-pseudocode)
public class Field
{
public Piece piece {
public Field field {
public Piece piece {
...
}
}
}
}
That's because the objects are defined in terms of each other. Then theoretically you can
do something like
this.field.piece.field.piece...

Model Relationships: efficiency in defining the relationship within the model

A bit of a high-level question, more for the academics than the trench-diggers, I suppose.
Question 1:
When defining a foreign relationship with another model, say, a one-to-many relationship, it is typically defined in the following manner:
public virtual ICollection<OtherModel> OtherModel { get; set; }
However, I have also seen it defined in the following manner:
private ICollection<OtherModel> _otherModel;
public virtual ICollection<OtherModel> OtherModel {
get { return _otherModel ?? ( _otherModel = new List<OtherModel>() ); }
set { _otherModel = value }
}
This does make sense to me: if no entries of this model are referenced from the OtherModel (a null value), then the null-coalescing operator ensures that a blank, empty collection of OtherModel is created. From what I can tell, it’s a safety measure.
However, an evolution of the above appears to be this:
public class ThisModel {
// Assorted model items
public virtual ICollection<OtherModel> OtherModel { get; set; }
public ThisModel(){
OtherModel = new List<OtherModel>();
}
}
Unfortunately, I am not seeing how the two can be equivalent. The second code block above clearly uses the null-coalescing operator to call a blank list ONLY when OtherModel does not reference anything in ThisModel; when the resulting list would be null anyhow.
And when I read the third code block, I am interpreting it as a list of the OtherModel being created every single time ThisModel is called.
I was hoping someone could give me a bit of clarification on any differences between the two.
Question 2:
On the flip side of the coin, we have required entries in the OtherModel. Normally we build the reverse relationship in the OtherModel like this:
public virtual ThisModel ThisModel { get; set; }
However I have also seen it defined in the following manner:
public class OtherModel {
// Various model stuff
private ThisModel _thisModel;
public virtual ThisModel ThisModel {
get { return _thisModel; }
set {
if (value == null) throw new ArgumentNullException(nameof(value));
_thisModel= value;
ThisModelId = value.ThisModelId;
}
}
}
The key thing is, because OtherModel has a required foreign key, if that foreign key ends up being force-fed a null entry, the if statement explicitly throws a null exception. I like this. It ensures that for required foreign keys, a null value cannot be used or cannot be introduced. It ensures that any such rejection is done long before anything reaches the DB in a CRUD operation, and acts as a backup in case the business logic (higher up in the stack, with the View Models) was accidentally not extended to cover that issue.
My question in this case is how to condense this into something more efficient.
You are correct. They are different, and the constructor version is actually an anti-pattern. In the constructor, you're initializing an empty list whether or not the list has a value or not. For example, if EF were to initialize an instance where the list does have a value, first the value would be set to an empty list, then it would be set again to the list it should contain by EF. Granted, it's not that inefficient to simply create an empty list, but you are still consuming some amount of RAM and CPU for the operation that end up being unnecessary.
The custom getter and setter version is lazy-set, so an empty list is only initialized when the value is null, meaning no wasted resources. Again, it's not a huge deal, but a ton of little inefficiencies like this can eventually add up to real problems (like death by a thousand cuts).
Just to add a further wrinkle, though: in C# 6.0 you can actually provide a default without using a custom getter and setter, though. So the following is really the most optimal way:
public virtual ICollection<OtherModel> OtherModel { get; set; } = new List<OtherModel>();
It works exactly the same as the custom getter/setter version, just without all the cruft.

Comparison of unspecified generic properties

Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}

Is Enum Right For This? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm working on a Model and am using enum for a list of named items.
class Verse
{
public int Number { get; set; }
public string Text { get; set; }
}
class Chapter
{
public int Number { get; set; }
public List<Verse> Verses { get; set; }
}
class Book
{
public string Name { get; set; }
public List<Chapter> Chapters { get; set; }
}
class Bible
{
public Versions Version { get; set; }
public List<Book> Books { get; set; }
}
enum Versions
{
asv1901,
bbe,
darby,
kjv,
nasb,
niv,
nkjv,
nlt,
rsv,
web,
ylt
}
That seemed like a logical way to do it, but I'm finding that working with enum is adding unnecessary difficulty.
foreach (var chapter in chapters)
{
var bibleitem = new Bible();
bibleitem.Version = (Versions)Enum.Parse(typeof(Versions), chapter.version);
}
Would it make more sense to just use string[] or something? I'm sure there is some added benefit, to enum, but I question my benefit.
The guidance from Microsoft is here:
https://msdn.microsoft.com/en-us/library/ms229058%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
In particular note: Do not use an enumeration for open sets
People write new Bibles all the time, so your set of enumerated values could change. You would be better off using string constants, for instance, where you could add more at will.
While we are at it, some additional critiques of your code.
class Verse
{
public int Number { get; set; }
public string Text { get; set; }
}
Why is this a class, and why are the properties settable? Do you envision having an existing Verse in hand, and wishing to change its number and text to something different? If not, then don't allow it. I would write this as
struct Verse
{
public int Number { get; private set; }
public string Text { get; private set; }
public Verse(int number, string text) : this()
{
this.Number = number;
this.Text = text;
}
}
Once it is created, it does not change. Also, this is a small immutable thing that is logically a value, so make it a struct.
class Chapter
{
public int Number { get; set; }
public List<Verse> Verses { get; set; }
}
Again, if you have an existing chapter, do you intend the set of verses to change? Because anyone can call Add on a list. Also, this constrains you to having the list available at all times, rather than computed lazily from a database. Make this IEnumerable<Verse>.
enum Versions
{
asv1901,
bbe,
This violates both naming guidelines and general legibility. Spell things out! AmericanStandardVersion1901 is far better than asv1901.
You should use enums when you have a named list of constants in your code and you know that this particular list is not gonna change over time (hence called names list of constants).
what benifits do you get?
READABILITY. Using enums increases the readability of your code. Consider the scenario where I have 2 employee types: Permanent and ContractBased. Now I can do this in my code like this:
if employee.Type == 1
// deal with permanent employee
else if employee.Type == 2
// deal with contract based employee here
such code is hard to read and maintain as no one could guess what employee.Type == 1 or what employee.Type == 2 means.
If I define an enum instead like this:
enum EmployeeType { Permanent=1, ContractBased=2 }
my code becomes like this:
if employee.Type == EmployeeType.Permanent
// deal with permanent employee
else if employee.Type == EmployeeType.ContractBased
// deal with contract based employee here
the readability of code gets maximized and also I have intellisense available.
The problem with strings:
1) you would end up having hard-coded string literals in your code
2) no intellisense
3) more memory consumption
how to deal with added complexity?
you should have an enum type variable for chapter.Version (which is right now missing) instead of int. that way you wouldnt need to do the parsing.
but I'm finding that working with enum is adding unnecessary difficulty.
it depends on your needs. if your set will not change enum is the best way to go as it adds a more control with a verbose description and limited set that cannot be bypassed when you work with many developers on the same project.
But
if your set can change during the development of the solution and you can't preview the set than a string would be the better way to go
Enums usually work best when:
No one adds or removes records to it anytime soon (hopefully never).
You don't need to use the real value behind your enum records.
You don't need to use the name of your records.
Enum.Parse can be used to get the enum record from a string, but as you noticed it's pretty ugly and I discourage you from using it. If you have the integral enum value you can simply perform a cast like this:
Versions version = (Versions)0;
But note that an enum is not guranteed to be of type int, it could also be any other integral value. int just happens to be the default. I do however also discourage you from relying on the enum's real integral value because something like this is also possible:
public enum Versions
{
One = 1,
Two = 2,
Three = 3
}
public void Do()
{
Versions version = (Version)-9;
// version is now Versions.One.
// Its value however is -9, what kind of version should -9 be?
}
The code above runs without errors because the runtime doesn't perform any checks on the value you are using for the cast.
The answer to your question depends on the nature of Versions. If you believe it will not be changed in the future then it is a good canditate for an enum in most cases. But you should use the enum everywhere across your application. I see in your sample that you are using the version as a string and therefore need to perform an ugly Enum.Parse. Consistency is an important factor when using enums, well it always is but it doesn't hurt to point it out again.
If you think your records are of a more dynamic nature you are probably best suited with strings. In that case you should use strings consistently. (Just wanted to point it out once again)
using the enum provides methods for comparing instances of this class, converting the value of an instance to its string representation, converting the string representation of a number to an instance of this class, and creating an instance of a specified enumeration and value.
Correcty using im class.
Exp.
public enum Versions
{
asv1901,
bbe,
darby,
kjv,
nasb,
niv,
nkjv,
nlt,
rsv,
web,
ylt
}
Next, implement
foreach (var chapter in chapters)
{
var bibleitem = new Bible();
bibleitem.Version = (Versions) "Your class enum"(typeof(Versions), chapter.version);
}
Enum and more used for good programming practices, clean code
Referency using enum: Enum Class Microsoft

Bit of a brain teaser: Custom logic strings with C# classes

So, my basic set up is like so: I have items, which are restricted to different classes. These items have effects, which are also restricted to different classes. For example, I might have an item that may only be wielded by elves, while another item might be wielded by everyone, but gives specific bonuses/effects to elves.
Here's a Restriction class:
public class Restriction {
private int _base_id = 0;
private bool _qualify = true;
public Restriction() { }
// ... Base_ID and Qualify getters and setters here
public virtual bool Check(int c) {
if(_qualify) { return c == _base_id; }
else { return c != _base_id; }
}
A child of the Restriction class might be RaceRestriction, which only overrides the constructor:
public RaceRestriction(reference.races r, bool qual) {
Base_ID = (int)r; Qualify = qual;
}
reference.races r is an enum in a reference file. The idea here is that I can extend this "Restriction" syntax to any class that I define in the reference file -- so I can make Restrictions on race, class, stats, whatever I need.
So, this all culminates later, when I define (for example) an item, which has restrictions on who can equip it.
Below is a snippet from the Equipment class, where I define a piece of equipment for later use (hopefully it's readable as is):
public Equipment() {
...
_master_equipment_list[1] = new Equipment {
Name = "Sword",
Description = "It's just a sword for demonstration",
Stats = {
new Attribute {
Stat_Modifier = new KeyValuePair<reference.stats, int>(reference.stats.ATTACK, 5),
Restrictions = {
new RaceRestriction(reference.races.TROLL, false)
}
}
},
Restrictions = {
new ClassRestriction(reference.class.WARRIOR, true)
}
}
So the idea behind this is that using this system, I've defined a sword that can only be used by warriors (base warrior true restriction on the item), and it gives 5 attack to any trolls wielding it.
What I've cornered myself into is that this will only work for either logical AND or logical OR strings of thought. Say my item says "warriors can use this" and it says "elves can use this." Do I really mean "warriors or elves" or do I mean "warrior elves?"
That distinction, I think, is going to be necessary -- so I need to attach some logic to each restriction and make, essentially, I think, sets of restrictions that are tied to one another, that string with other sets of restrictions, etc., but I feel like that will get out of hand very fast.
Is there a better way I can do this?
Rather than defining specific restriction classes, I would design this by defining an interface called IRestrictable to be implemented by the Equipment classes. This interface would contain at least one method called CheckEligibility (or similar) which would return a bool. Your equipment class would then be free to use whatever logic expression it liked to come up with the answer, based on whatever inputs you wanted and whatever information the class had available at the time. You could have several methods on the interface if you need to check restrictions under different circumstances. You would be free to implement specific classes deriving from Equipment for specific types of equipment that had complicated rules.

Categories

Resources