Cant access subclass methods of object in Dictionary - c#

I am trying to store objects that are only a subclass of an Abstract Class. However, I can only see the abstract class methods and none of the subclass methods. What have I missed?
Class with Error in:
class CharacterStats
{
private Dictionary<StatType, Stat> playerStats;
//Contructor for new game
public CharacterStats()
{
playerStats = new Dictionary<StatType, Stat>();
//Creates all Stats with default values
playerStats.Add(StatType.STA, new StatSta());
playerStats.Add(StatType.STR, new StatStr());
playerStats.Add(StatType.DEX, new StatDex());
playerStats.Add(StatType.DEF, new StatDef());
}
//Returns the damage reduction in %
public int GetDamageReduction()
{
playerStats[StatType.DEF]. //Missing Methods from StatDef class
//Added to remove error message
return 1;
}
}
Abstract Class:
abstract class Stat
{
protected int pointsAdded;
protected int pointCap;
public Stat() {}
public string TestMethod()
{
return "Working!";
}
}
Subclass:
class StatDef : Stat
{
public StatDef() : base()
{
this.pointsAdded = 0;
this.pointCap = 100;
}
public int ApplyDamageReduction(int dmg)
{
//removed data to read easier
return 1;
}
}
Thanks

The type of the expression playerStats[StatType.DEF] is just Stat. The compiler doesn't know what kind of Stat is stored as the value there.
If it will always be a StatDef, then you should just cast:
var def = (StatDef) playerStats[StatType.DEF];
// Now you can use def.ApplyDamageReduction etc
However, you'll need to cast any time you want to use a stat-specific member. Unless you often want to treat multiple stats in the same way, I'd suggest ditching the dictionary approach and just having separate fields:
class CharacterStats
{
private StatDefence defence;
private StatAttack attack;
private StatStrength strength;
// etc
}
You could easily write a method that allows you to iterate over all the stats for the times where that is useful:
public IReadOnlyList<Stat> GetAllStats() =>
new Stat[] { defence, attack, strength, ... };
But my suspicion is that most of the time you're using the stats, you actually want to know a specific stat. I'd always rather write:
var strength = stats.Attack;
than
var strength = stats[StatType.STR];
even if when I don't need the specific aspects of the strength statistic.

Related

Swap base class at runtime?

I know it had been asked a very long time ago, but no answers were really helpful, C# changed a lot since then and my problem is a bit different.
I'm in an environment that allows custom DLL loading, so people can add their content to the running program, let's say, submodules, but of course it comes at costs of some restrictions.
(Edited the example)
Example, none of this code exists
Public abstract class Car
{
int tires=4;
string color;
public Car(string c){
color = c;
}
}
public class SportCar : Car{
int doors = 3;
int maxspeed=100;
public void changeSpeed(int i){
maxspeed = i;
}
}
public class Ferrari : Car{
string model = "Ferrari";
}
What i want to have after is
public ClassResult{
int tires=4;
string color;
int doors = 3;
int maxspeed=100;
string model = "Ferrari";
public ClassResult(string c){
color = c;
}
public void changeSpeed(int i){
maxspeed = i;
}
}
So i asked for inheritance cause shown like this the problem is solved really easily if you have control over the code and can rewrite it. But i do not.
The only thing i can do is post process it to have the end result.
So changing at runtime the mother class of Ferrari or SportCar in the example would solve it, as it would be a classic inheritance but it might be another way.
Currently how i handle the issue is by discarding one of the child classes, but it's not really satisfying and may lead to other issues.
What exact control i have, is a class over all of those, that contain a collection of added classes. And i call some methodes inside of them that they are all supposed to implement. (That's why they all inherit the same base class)
Hope it's clearer this way.
My suggestion would be to look in the direction of composition instead of inheritance.
Based on your example code, I would suggest the following composition:
(PS. this is just pseudo code to get the point across for composition, I typed it here, there are probably some build errors :p)
public class Car
{
public List<CarModule> Modules;
public InvokeMethod(string methodName)
{
Module moduleWithMethod = Modules.FirstOrDefault(m => m.HasMethod(methodName));
moduleWithMethod.InvokeModuleMethod(methodName);
}
}
public abstract class CarModule
{
protected abstract Dictionary<string,Action> _moduleMethods;
public bool HasMethod(string methodName) => _moduleMethods.Keys.Contains(methodName);
public void InvokeModuleMethod(string methodName)
{
_moduleAction[methodName].Invoke()
}
}
public sealed CarMovement : CarModule
{
int _speed = 5;
const int _maxSpeed = 100;
private Dictionary<string,Action> _moduleMethods =
{
["ToMaxSpeed"] = () => ToMaxSpeed()
}
private void ToMaxSpeed()
{
_speed = maxSpeed;
}
}
public class Test
{
public void TestCase()
{
var speedingCar = new Car();
speedingCar.Modules.Add(new CarMovement());
speedingCar.InvokeMethod("ToMaxSpeed");
}
}
Ofcourse I would not suggest using the Action type as a value for the dictionary, but rather use the command pattern to encapsulate the behaviours. Or something like that. But hopefully this gets you somewhere

Inheritance in c# and object creation in c#

I have classes as follow one is SuperClass which is inherited by ChildClass and Child1Class
public class SuperClass
{
public new int Superclassprop = 2;
public virtual void play()
{
Console.WriteLine("SuperClass");
}
}
public class ChildClass : SuperClass
{
public new int Childclassprop = 2;
public override void play()
{
Console.WriteLine("ChildClass");
}
}
public class Child1Class : SuperClass
{
public new int Childclassprop = 3;
public override void play()
{
Console.WriteLine("Child1Class");
}
}
Now when i create an object something like below i don't understand what is the difference between these. i had read a huge bunch of blogs related to this but i didn't find any justifiable answer please help me to understand what actually is happening here or suggest me a good blog or article including on SO where i can understand a whole concept behind this why we need this where the actual real time use of these concept?
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
I have attached screenshot of watch which is generating on Run-Time why there is a obj1 consisting all properties but i can access only SuperClassprop?
Thanks in advance any help will be really appreciated.
Here is the more practical example of your topic:
using System;
public class Music
{
public virtual string play()
{
return "Play Music";
}
}
public class Drum : Music
{
public override string play()
{
return "Play Drums";
}
}
public class Piano : Music
{
public override string play()
{
return "Play Piano";
}
}
public class PlayMusicService
{
private readonly Music _musicContext;
public PlayMusicService(Music musicContext)
{
this._musicContext = musicContext;
}
public string PlayAlbum()
{
return _musicContext.play();
}
}
public class Program
{
public static void Main()
{
string whatPlayed = "";
Drum drums = new Drum();
PlayMusicService music1 = new PlayMusicService(new Drum());
whatPlayed = music1.PlayAlbum();
Console.WriteLine(whatPlayed);
Piano piano = new Piano();
PlayMusicService music2 = new PlayMusicService(new Piano());
whatPlayed = music2.PlayAlbum();
Console.WriteLine(whatPlayed);
}
}
Output:
Play Drums
Play Piano
i don't understand what is the difference between these.
One of the main differences is the constructor call
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
In the case of obj1 the ChildClass constructor is called after the SuperClass constructor and the field and property initialisation is done also for the property Childclassprop
consisting all properties but i can access only SuperClassprop?
The variable obj1 is still of type SuperClassprop so at compile time you are only allowed to see and use those variables that belong to this class. If you want to actually access the variables of ChildClass you will have to cast it to the proper type:
var r = (obj1 as ChildClass).Childclassproput;
why we need this where the actual real time use of these concept?
One scenario that comes to my mind is : it might be that at compile time it is not clear which class has to be instantiated. But this is decided at runtime. But you need already a variable to write the call of the specific play() method. At runtime it will be decided which method is called in the end.
SuperClass obj = new SuperClass();
bool condition = false;
if (condition)
{
obj = new ChildClass();
}
else
{
obj = new ChildClass1();
}
// now just call the method and the proper method will be called
obj.play();

How do I make T work with intherited classes?

I'm programming a dungeon generator for a roguelike. I've a base class called Room. It contains methods that can be inherited by other types of rooms. It looks like this but then a little more advanced
class Room
{
protected virtual void Construct() { /*make square room here*/ }
}
class RoundRoom : Room
{
protected override void Construct() { /*make round room here*/ }
}
My class that generates rooms needs to be "fed" with rooms to generate. The room handles the construction, and I've different types of rooms. And I want it to have it that certain specific rooms can be generated based on some conditions or chances.
So I feed it with different types of rooms. First I thought of this:
class RoomEntry
{
public Point chance;
public Room room;
}
And then have an array of it
RoomEntry[] entries;
And then just feed it
Generator.Feed(entries[random.Next(0, 10)].room); // just an example
But that won't work! If I edit the room in the generator, It'll change in RoomEntry too! And I need to use it quite a few times!
So if I would make new rooms based on some room type... It'll work!
So I came up with this:
class RoomPlanner
{
class RoomEntry<T> where T : Room, new()
{
public Point chance;
T r;
public Room RoomToBuild()
{
return new T();
}
}
RoomEntry<Room>[] entrys;
public void Foo()
{
entrys = new RoomEntry<Room>[10];
for (int i = 0; i < entrys.Length; i++)
{
entrys[i] = new RoomEntry<RoundRoom>();
}
}
}
But that's not possible. I'm getting this error:
Cannot implicitly convert type 'Super_ForeverAloneInThaDungeon.RoomPlanner.RoomEntry<Super_ForeverAloneInThaDungeon.RoundRoom>' to 'Super_ForeverAloneInThaDungeon.RoomPlanner.RoomEntry<Super_ForeverAloneInThaDungeon.Room>'
So, how do can I make it accept classes that inherit from Room, or how do I take a different approach to this problem?
It's not an duplicate of this. That's a different problem, and I do not have enough information to fix my problem entirely out of it.
The problem is that covariant/contravariant type parameters can only be used with interface or delegate types. (More information on that in this MSDN article.) Essentially, there is no way to declare a RoomEntry<T> that is contravariant with RoomEntry<Room>, even with the constraint that T : room.
You could get around this by defining an IRoomEntry interface that is implemented by RoomEntry<T>, like this:
interface IRoomEntry
{
Room RoomToBuild();
}
class RoomPlanner
{
class RoomEntry<T> : IRoomEntry
where T : Room, new()
{
public Point chance;
T r;
public Room RoomToBuild()
{
return new T();
}
}
IRoomEntry[] entrys;
public void Foo()
{
entrys = new IRoomEntry[10];
for (int i = 0; i < entrys.Length; i++)
{
entrys[i] = new RoomEntry<RoundRoom>();
}
}
}
Seems like you just want to Clone the room before feeding it to the Generator. You could just add a Clone method to your Room class:
Room Clone() { return (Room)this.MemberwiseClone(); }
And then feed it like so:
Generator.Feed(entries[random.Next(0, 10)].room.Clone());

C# Cross-Class object

I'm working on very simple Roguelike game (just for myself) and get a question:
As it is not possible to create a cross-class struct-object (entity in the game case) that could be accessible from any class of my program, what to use to create a cross-class object? I was thinking of something like storing all newly created object (enities) in a static object array, but I guess there is more simple solution on this problem.
Question itself: How to create a cross-class accessible object(s) with your own properties?
Thanks everybody, I found what I was searching for.
It seems like you tried passing around a value type (a struct) between different classes and you noticed that when you update the value in one place it doesn't change the value in another place.
That's the basic difference between value types and reference types.
If you are creating the struct yourself you may want to instead define it as a class.
If not, you could wrap all your structs in a class and pass the class around as your state object.
If all you have is simply a list of the same type of struct (like Points), just pass the List itself around. C# collections are implemented as classes.
public class GameState
{
public Point PlayerLocation { get; set; }
public List<Point> BulletPoints { get; set; }
public double Health { get; set; }
}
Now you can create a GameState and pass it around to different classes:
public class Game
{
private GameState _state = new GameState();
private BulletUpdater _bulletUpdater = new BulletUpdater();
public void Update()
{
_bulletUpdater.UpdatePoints(_state);
// Points have now been modified by another class, even though a Point is a struct.
}
}
public class BulletUpdater
{
public void UpdatePoints(GameState state)
{
for (int i = 0; i < state.BulletPoints.Count; i++)
{
Point p = state.BulletPoints[i];
state.BulletPoints[i] = new Point(p.X + 1, p.Y + 1);
}
}
}
Just remember in the above code if I were to write:
Point p = state.BulletPoints[i];
p.X += 1;
p.Y += 1;
That wouldn't affect the original point! When you read a value type from a list or from a class into only copies the value into a local variable. So in order to reflect your changes in the original object stored inside the reference type you need to overwrite it like so:
state.BulletPoints[i] = p;
This same principal is why the following also will not work:
state.PlayerLocation.X += 5; // Doesn't do anything
state.PlayerLocation.Y += 5; // Also doesn't do anything
The compiler would tell you in this case that you are doing something wrong. You are only modifying the returned value of the property, not the backing field itself. You have to write it like so:
state.PlayerLocation = new Point(state.PlayerLocation.X + 5, state.PlayerLocation.Y + 5); // This works!
You can do the following:
Using IoC Framework, like Ninject. You can setup Ninject to create single instance for all usages.
The other option is to use Singleton pattern design pattern
And the third one is to use static property
It sounds like you want to use the Singleton pattern:
http://en.wikipedia.org/wiki/Singleton_pattern
Here is an example of what this would look like in C#:
public class Singleton
{
static Singleton()
{
Instance = new Singleton();
}
public static Singleton Instance { get; private set; }
}
It's possible. What about public and static class?
public static class CrossClassObject
{
public static object MyProperty { get; set; }
public static void MyMethod() {}
}
Of course this class should be placed in the same namespace that other ones.
How to use it?
class OtherClassInTheSameNamespace
{
private void SomeMethod()
{
var localVariable = CrossClassObject.MyProperty; // get 'cross-class' property MyProperty
CrossClassObject.MyMethod(); // execute 'cross-class' method MyMethod()
}
}
No idea what you are trying to achieve... but if you want a list of objects accessible 'cross-class', just make a static class with a list of objects and then when you reference your class from any other class, you will have access to its list of objects. Here is something like that:
public static class ObjectController
{
private static IList<object> existingObjects;
public static IList<object> ExistingObjects
{
get
{
if (existingObjects == null)
{
existingObjects = new List<object>();
}
}
}
}
public class MyObject
{
public MyObject()
{
ObjectController.ExistingObjects.Add(this);
}
public void Delete()
{
ObjectController.ExistingObjects.Remove(this);
}
}
Then you can add stuff like
MyObject newObj = new MyObject();
//// other stuff... This object should now be visible to whatever other class references ObjectController
newObj.Delete();

C# value/reference passing?

I have a declared entity of a class, and want to assign different pre-made templates to it without the templates ever changing. Using a const doesn't seem to do the trick.
Example:
Weapon w1;
w1 = Sword; // premade weapon.
w1.reducedamage(1); // for example a debuff
In this case the premade weapon's damage would be decreased, and it would no longer be available as a template. This problem becomes more profound with enemies.
Example:
Enemy enemy;
enemy = enemies[r] // r being a randomly generated integer and enemies a list of enemy templates
Fight(player,enemy); // this method would resolve a fight between the two entities of the type Character.
This problem would not be visible in the player class, since player is a single reference being passed along all the game methods - because there is only one player. Every time the player fights, an enemy template would be "corrupted".
How would I create templates or classes/structs in general that always pass by value, meaning that the properties of a first class would have the same values as a second, without any relationship between the two classes?
The only success I've gotten with this is to create a method that manually copies each attribute of every class that has a template onto another entity of the same class; but this is extremely unpractical since it needs constant upgrading whenever a new class is added, or an old one changed.
I must be missing something. This seems like a reasonably simple issue that is easily solved by inheritance, perhaps in conjunction with some sort of Factory. First, you don't want to use a reference to a single instance, you want to create a new instance each time so it is a unique object. I prefer classes over structs, but you could easily create a new struct as well. You could use a Factory to create various pre-configured instances of the objects that have pre-defined values. For example, the Sword of Damocles or the Sword of Destiny.
public static class WeaponFactory
{
public static Weapon CreateSword(SwordType type)
{
var sword = new Sword(); // plain, old default sword
// override properties based on type
switch (type)
{
case SwordType.SwordOfDamocles:
sword.FallTime = GetRandomFutureTime();
break;
case SwordType.SwordOfDestiny:
sword.Invincible = true;
break;
...
}
return sword;
}
...
}
Alternative using Actions
public static class WeaponFactory
{
public static Weapon Create<T>(Action<T> decorator) where T : IWeapon, new()
{
var weapon = new T();
decorator(weapon);
return weapon;
}
public static void SwordOfDamocles(Sword sword)
{
sword.FallTime = GetRandomFallTime();
}
public static void SwordOfDestiny(Sword sword)
{
sword.Invincible = true;
}
}
var weapon = WeaponFactory.Create(WeaponFactory.SwordOfDamocles);
What you want is object cloning. You can implement it via the ICloneable interface[1]. That requires that you implement your own cloning mechanism though--you have to do the heavy lifting.
However, what you probably should do instead is just have the constructor take a parameter that represents the template you want, and then fill the properties of the object in question based on that template. That's the direction I go when I want to make duplicate things with a base set of values.
You could do actual copying (e.g. provide a copy constructor as in http://msdn.microsoft.com/en-us/library/ms173116(v=vs.80).aspx ), but what I've seen most often in such cases is a factory pattern, e.g. Weapon w1 = Weapon.CreateSword(); or Enemy e=Enemy.CreateEnemyOfType(r);
you could build a method to return multiple enemies in either a generic collection or array into your enemy class. Something like:
public shared function getEnemies(num as integer, type as string) as list(of clsEnemy)
dim enemyGroup as list(of clsEnemy)
for i = 0 to num - 1
dim thisEnemy as new clsEnemy(type)
enemyGroup.add(thisEnemy)
next
return enemyGroup
end function
Contrary to copying objects to implement some kind of "applied object" pattern, it's good to keep in mind it's not the sword "base item" that is being altered, but the item your player is carrying.
For example, a given sword, say "rusty old sword", will always have a base damage of 50. Now if someone applies "old stuff gets better magic" to it, it's not the "rusty old sword" that gets more damage: if some other player that hasn't got that kind of magic picks up the item, it's back to its base damage of 50.
So if you implement some kind of EquippedWeapon (or even EquippedItem) class, you can let your player equip weapons and give it extended properties. Something like this to declare a Sword:
interface IWeapon
{
int Damage { get; }
}
class Sword : IWeapon
{
public int Damage { get; private set; }
public Sword()
{
this.Damage = 50;
}
}
Now we have a sword with a base damage of 50. Now to let the player carry this sword:
interface IDamageModifier
{
int Damage { get; set; }
}
class EquippedWeapon : IWeapon
{
public int Damage
{
get
{
return CalculateActualDamage();
}
}
public List<IDamageModifier> DamageModifiers { get; set; }
private IWeapon _baseWeapon = null;
public EquippedWeapon(IWeapon weapon)
{
_baseWeapon = weapon;
}
private int CalulcateActualDamage()
{
int baseDamage = _baseWeapon.Damage;
foreach (var modifier in this.DamageModifiers)
{
baseDamage += modifier.Damage;
}
return baseDamage;
}
}
A weapon contains a list of active modifiers, that affect the damage of the carried item, but not the base item. This way you can share one Sword instance with many (non-)playable characters.
Now if the player gets attacked and that attack has a damage effect, you simply apply that to the item(s) the player is carrying, so each successive attack from that player will have those effects applied:
class Player
{
public EquippedWeapon PrimaryWeapon { get; set; }
public Player()
{
this.PrimaryWeapon = new EquippedWeapon(new Sword());
}
public void UnderAttack(Attack attack)
{
// TODO: implement
if (attack.Buffs...)
{
this.EquippedWeapon.DamageModifiers.Add(attack.Buffs);
}
}
}
I wrote an answer answering your question directly. But now I see that all you want is to create items that are the same but not linked.
That's what happens anyway when you create an instance. You don’t have to do anything.
If you have:
class Class1
{
public int i;
}
Then:
Class1 c1 = new Class1() { i = 1 };
Class1 c2 = new Class1() { i = 2 };
Text = c1.i.ToString();
Prints "1", not "2".
And if you mean you want a "Player" class with sub-classes "Friend" and "Foe" - That's what inheritance is for:
class Player
{
}
class Friend : Player
{
}
class Foe : Player
{
}
EDIT:
Perhaps this will make the task easier: (The "Duplicate" method)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Class1 c1 = new Class1() { i = 1, j = 2 };
Class1 c2 = Duplicate(c1);
c1.i = 3;
Text = c2.i.ToString();//Prints "1";
}
public Class1 Duplicate(Class1 c)//Duplicates all public properties.
{
Class1 result = new Class1();
PropertyInfo[] infos = typeof(Class1).GetProperties();
foreach (PropertyInfo info in infos)
info.SetValue(result, info.GetValue(c, null), null);
return result;
}
}
public class Class1
{
public int i { get; set; }
public int j { get; set; }
}

Categories