C# base class have a derived class member and it loops - c#

I have this class:
public class GameData
{
public int[,] mat { get; set; }
public int dim { get; set; }
public int goal { get; set; }
public Game game { get; set; }
public GameData()
{
game = new Game();
}
}
And this two other derived classes:
public class Game :GameData
{
private Mover m;
public Game()
{
dim = 4;
goal = 16;
mat = new int[dim, dim];
m = new Mover();
}
/*Methods*/
}
public class Mover : GameData
{
/*Methods*/
}
It loops because Game constructor calls GameData constructor and so on.
How can I do?
I am starting whit OOP programming and I am not sure this three classes are the best way to set the program. GameData contains common datas, Game contains the method to play and Mover contains a group of method used by Game

Honestly inheritance doesn't make any sense here. Inheritance is an "is a type of" relationship (in other words, is Game a type of GameData? I doubt it.
Instead use composition! Just have class hold the objects they care about. Composition is a "has a" relationship, which makes a lot more sense in your case. Honestly, I would invert the Game/GameData relationship, a Game probaly holds GameData; not the other way around. Only you know what you need though.
public class GameData
{
public int[,] mat { get; set; }
public int dim { get; set; }
public int goal { get; set; }
public Game game { get; set; }
public GameData()
{
game = new Game();
dim = 4;
goal = 16;
mat = new int[dim, dim];
}
}
public class Game
{
private Mover m;
public Game()
{
m = new Mover();
}
/*Methods*/
}
public class Mover
{
/*Methods*/
}

This sentence
public GameData()
{
game = new Game();
}
makes no sense; as GameData is the parent, is not logical to have a child inside the parent. Obviously that makes a loop, as you are creating a Game : GameData over and over with that sentence.
Think about inheritance you want, as you are using it incorrectly with Mover too.

Well you definitely have a circular reference which is a design smell. You could stop the infinite loop by checking for null:
public GameData()
{
if(game == null)
game = new Game();
}
Or pass the Game instance in to the constructor rather than creating a new one - hard to say what's correct without knowing more of your overall design.

Related

Different types in C# Interface Implementation

I really struggle entitling this, but i'll try my best at explaining my point.
Say i have this :
List<IShape> Shapes = new List<IShape>();
public interface IShape {
dynamic shapeAttributes { get; set; }
};
public struct SquareAttributes {
float sizeOfSide;
};
public struct CircleAttributes {
float radius
};
public class Square : IShape {
SquareAttributes shapeAttributes { get; set; }
};
public class Circle : IShape {
CircleAttributes shapeAttributes { get; set; }
};
Shapes.Add(new Square());
Shapes.Add(new Circle());
How Do I make that situation work ? Here the "dynamic" keyword in IShape is not resolved when implemented in Square and Circle, but I'd still want to be able to define the right Type when implementing rather than using "dynamic" everywhere. Is there a right way to deal with this, with the ability re regroup all kind of Shapes in the same list? I hope this is clear.
I obviously simplified the whole thing to get straight to the point, but everything involved is far more complex and cannot really be fitted into a single large piece.
If your shapes attributes very different you can use System.Object as common type. But don't forget to check if you pass correct ShapeAttributes type to correct implementation of IShape, so I recommend to use set method instead of property setter:
Objects definition:
public interface IShape
{
object ShapeAttributes { get; }
Type ShapeAttributesType { get; }
void SetAttributes(object shapeAttributes);
}
public class Square : IShape
{
public object ShapeAttributes { get; private set; }
public Type ShapeAttributesType => typeof(SquareAttributes);
public void SetAttributes(object shapeAttributes)
{
// Check if passed correct type
if (shapeAttributes.GetType() != ShapeAttributesType)
throw new ArgumentException($"Argument type must be {ShapeAttributesType.FullName}", nameof(shapeAttributes));
ShapeAttributes = shapeAttributes;
}
}
public class Circle : IShape
{
public object ShapeAttributes { get; private set; }
public Type ShapeAttributesType => typeof(CircleAttributes);
public void SetAttributes(object shapeAttributes)
{
// Check if passed correct type
if (shapeAttributes.GetType() != ShapeAttributesType)
throw new ArgumentException($"Argument type must be {ShapeAttributesType.FullName}", nameof(shapeAttributes));
ShapeAttributes = shapeAttributes;
}
}
public struct SquareAttributes
{
public float SizeOfSide { get; set; }
}
public struct CircleAttributes
{
public float Radius { get; set; }
}
Usage example:
List<IShape> shapes = new List<IShape>();
var square = new Square();
square.SetAttributes(new SquareAttributes()
{
SizeOfSide = 4.1f
});
var circle = new Circle();
circle.SetAttributes(new CircleAttributes()
{
Radius = 2.12f
});
shapes.Add(square);
shapes.Add(circle);
foreach (var shape in shapes)
{
//Cast ShapeAttributes based on owner class type
switch (shape)
{
case Square s:
var size = ((SquareAttributes)s.ShapeAttributes).SizeOfSide;
Console.WriteLine($"Square.ShapeAttributes.SizeOfSide = {size}");
break;
case Circle c:
var radius = ((CircleAttributes)c.ShapeAttributes).Radius;
Console.WriteLine($"Circle.ShapeAttributes.Radius = {radius}");
break;
}
}

Covariance, generic, UserControl

I have created a user control that contains an ObservableCollection<Something>. I learned that I cannot cast say ObservableCollection<Tiger> to ObservableCollection<Animal>. The solution I found was to add a helper class that handles all low level collection manipulation. My suspicion is that there is a more elegant solution and if so, maybe someone can point me into that direction.
See the code below that captures the problem and my solution. Zoo corresponds to the WPF UserControl. (Actually a zoo for one type od animal.) Ideally I would define it as Zoo<T> i.e. as a generic type but that would prevent me from using XAML. I need to define Animals as object in order assign to it.
class Program
{
public static void Main(string[] args)
{
Zoo zoo = new Zoo();
List<Tiger> tigers = new List<Tiger>() { new Tiger() };
zoo.Animals = tigers;
zoo.Helper = new TigerHelper(tigers);
Console.WriteLine(zoo.GetCount());
Console.ReadLine();
}
}
public class Animal { }
public class Tiger : Animal { }
public interface Helper { int GetCount(); }
public class TigerHelper : Helper
{
private List<Tiger> tigers;
public TigerHelper(List<Tiger> tigers) { this.tigers = tigers; }
public int GetCount() { return tigers.Count; }
}
public class Zoo
{
public object Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Helper.GetCount(); }
}
Rather than go all the way down to object, you can use IList. This gives you access to most of the features of the list, but without the generics. For example, you can still access the Count property:
public class Zoo
{
public IList Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Animals.Count; }
}

Class Instance or Inherited Class for a game? Best Practice

So I'm building a small game framework to reinforce abstract classes and interfaces. I've been building classes for some mechanics and I'm not sure how to deal with the final pieces.
Here's the class framework (with some miscellaneous methods removed):
public abstract class Ability
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual string Type { get; set; }
public virtual string Stat { get; set; }
public virtual float Scale { get; set; }
public virtual float MPCost { get; set; }
public virtual float SPCost { get; set; }
}
public class Attack : Ability
{
public float BaseDmg { get; set; }
public bool isUnblockable { get; set; }
public float GetDmg(int stat)
{
return BaseDmg * (1 + stat * Scale);
}
}
Now for the actual Attacks I want to create, should I instantiate like I have been?
public static class AllAttacks
{
//Physical Attacks
public static Attack slash = new Attack();
//Magical Attacks
public static Attack push = new Attack();
public static void Generate()
{
//Physical Attacks
slash.Name = "Slash";
slash.Description = "A simple but effective strike.";
slash.Type = "physical";
slash.Stat = "str";
slash.Scale = 0.1F;
slash.MPCost = 0;
slash.SPCost = 1;
slash.BaseDmg = 5;
slash.isUnblockable = false;
//Magical Attacks
push.Name = "Push";
push.Description = "A powerful telekinetic strike.";
push.Type = "magic";
push.Stat = "int";
push.Scale = 0.1F;
push.MPCost = 1;
push.SPCost = 0;
push.BaseDmg = 5F;
push.isUnblockable = false;
}
Or should I actually create a new inherited class for each unique item and then instantiate them in the Fight class? And if I do, should these be static or non-static?
public class Slash : Attack
{
//Code Here
}
Could anyone point me to best practices or what the most efficient method would be?
Typically there are two main reasons to define a new class: new behavior and/or new contract, that is changed implementation for the former reason or added new public members for the latter. Now considering your example I don't see changed contracts or behaviors for various types of attack (only changed state) so I don't see a reason to define new classes for them. From the readability standpoint the Generate method isn't optimal however - I'd create separate methods for different types of attack which would clearly denote what type of attack they create.
As for the instantiation aspects, if you aren't going to mutate your attack instances than get them created in the single place is pretty okay, otherwise you need to control the life cycle of every attack instance on the level where the instance is used.

Can't seem to get OneToMany relation working

I'm very new to Mobile App Development so i'm trying to teach myself.
I'm using Xamarin and sqlite-net (extensions) for this particular app i'm trying to make.
I have 2 classes with a OneToMany relationship
class Game
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Player> Players { get; set; }
public Game()
{
Players = new List<Player>();
}
}
class Player
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(8)]
public string Name { get; set; }
[ForeignKey(typeof(Game))]
public int GameId { get; set; }
[ManyToOne]
public Game Game { get; set; }
}
Now in my activity I have something like this
SQLiteConnection db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), path);
db.CreateTable<Player>();
db.CreateTable<Game>();
Game game = new Game();
game.Name = "Stupid game";
Game game2 = new Game();
game2.Name = "Fun game";
Game game3 = new Game();
game3.Name = "Amazing game";
db.Insert(game);
db.Insert(game2);
db.Insert(game3);
Player player = new Player();
player.Name = name; //Getting this from a input field
db.Insert(player);
Random random = new Random();
player.GameId = random.Next(1, 3);
Game game = db.Get<Game>(player.GameId);
player.Game = game;
db.UpdateWithChildren(player);
game.Players.Add(player);
db.UpdateWithChildren(game);
This all seems to work and gives me no errors. When I debug this I can see that the player is indeed added with a Game. However when I try somewhere else to get all the players using the following statement,
List<Player> players = db.Table<Player>().ToList();
they suddenly don't have a Game anymore and my program crashes when I try to read that property.
I've tried a few different things with the UpdateWithChildren and InsertWithChildren but to no avail. Is there something I'm doing wrong or is it something I haven't installed or?
I really appreciate the help.
The thing about sqlite-net extensions is that you cannot go "Back" to using regular sqlite-net methods if you want to obtain children relationships. Thus you will have to follow their documentation here:
https://bitbucket.org/twincoders/sqlite-net-extensions
They provide methods such as GetChildren, UpdateWithChildren, etc in which you will have to use over the generic db.Table<T> methods.
If you decide to use the recursive methods, be sure to provide the optional recursive parameter.
Thus you should be able to do something along the lines of:
conn.GetWithChildren<Player>(identifier, recursive: true)
Otherwise read up more on the Cascade Operations section of the documentation linked above.

Sorting a `List<object>` by object properties

I have some different objects that all of them have a integer field called Place. Is there a way to sort out this list without knowing what is the actual object? I mean just accessing the Place field and sort the list based on this number. possibly using linq or something?
some example objects:
public class Car
{
public int Place;
//Other related fields
}
public class Human
{
public int Place;
//Other related fields
}
//Somwhere in program
List<object> GameObjects;
You should derive your classes from a base class.
public class Base
{
public int Place;
}
public class Car : Base
{
// other properties
}
public class Human : Base
{
// other properties
}
Then you can create a list of your base type, add humans
and cars. After that you can use the Linq Sort or OrderBy method.
List<Base> list = new List<Base>();
list.Add(new Human { Place = 2 });
list.Add(new Car { Place = 1 });
var sortedList = list.Sort(x => x.Place);
More Information
The C# Station Tutorial - Lesson 8: Class Inheritance
MSDN - Queryable.OrderBy
MSDN - List.Sort Method
No because object doesn't have a Place property only Car/Human do.
There are a couple of ways you can solve this problem:
Introduce a base class
public class GameObject
{
public int Place { get; set; }
}
public class Car : GameObject
{}
public class Human : GameObject
{}
...
List<GameObject> GameObjects
Use a generic interface
public interface IGameObject
{
int Place { get; }
}
public class Car : IGameObject
{
public int Place { get; set; }
}
public class Human : IGameObject
{
public int Place { get; set; }
}
List<IGameObject> GameObjects
What you just discovered is relationship between those types. Both Car and Human seem to have a Place property, so you should extract an interface à la IGameObject.
The best way is to use an interface. If you can't, you still can do late binding using the dynamic keyword:
var list = new List<object>
{
new Car { Place = 3 },
new Human { Place = 1 },
new Car { Place = 2 }
};
var sortedList = list.OrderBy(o => ((dynamic)o).Place);
Yes, its possible using delegate methods with reflection. This is upto my knowledge, may be some other giants create it without using reflection
The best you can do is use an Interface, like this:
public Interface IFoo
{
int place;
}
And the implement that interface:
public class Car : IFoo
{
public int Place;
}
public class Human : IFoo
{
public int Place;
}
And then with linq:
List<IFoo> GameObjects;
GameObjects.OrderBy(g => g.Place);
You could let them implement an interface IPlaceable and use a property instead of only a field:
public interface IPlaceable
{
int Place { get; set; }
}
public class Car : IPlaceable
{
public int Place { get; set; }
//Other related fields
}
public class Human : IPlaceable
{
public int Place { get; set; }
//Other related fields
}
// Somwhere in program
List<IPlaceable> GameObjects;
// Somwhere else
GameObjects.OrderBy(go => go.Place);
Note that the list now is a List<IPlaceable> instead of a List<Object>.

Categories