C#, generic way to access different lists within a class - c#

I have a class of 3 different linked lists (for saving the entities in a game I'm working on). The lists are all of objects with the same base type, but I keep them separate for processing reasons. Note that IEntity, IObject and IUndead all inherited from IEntity.
public class EntityBucket
{
public LinkedList<IEntity> undeadEntities;
public LinkedList<IEntity> objects;
public LinkedList<IEntity> livingEntities;
public EntityBucket()
{
undeadEntities = new LinkedList<IEntity>();
objects = new LinkedList<IEntity>();
livingEntities = new LinkedList<IEntity>();
}
public LinkedList<IEntity> GetList(IObject e)
{
return objects;
}
public LinkedList<IEntity> GetList(IUndead e)
{
return undeadEntities;
}
public LinkedList<IEntity> GetList(ILiving e)
{
return livingEntities;
}
}
I have 3 methods for retrieving each of the lists, currently based on their parameters. The fact that there are 3 is fine, since I know each list will in some way or another require its own accessor. Passing an instantiated object is not ideal though, as I may want to retrieve a list somewhere without having an object of similar type at hand. Note that the object here is not even used in the GetList methods, they are only there to determine which version to use. Here is an example where I have an instantiated object at hand:
public void Delete(IUndead e, World world)
{
.....
LinkedList<IEntity> list = buckets[k].GetList(e);
.....
}
I don't like this current implementation as I may not always have an instantiated object at hand (when rendering the entities for example). I was thinking of doing it generically but I'm not sure if this is possible with what I want to do. With this I also need 3 Delete methods (and 3 of any other, such as add and so forth) - one for each type, IUndead, IObject and ILiving. I just feel that this is not the right way of doing it.
I'll post what I have tried to do so far on request, but my generics is rather bad and I feel that it would be a waste for anyone to read this as well.
Finally, performance is very important. I'm not prematurely optimizing, I am post-optimizing as I have working code already, but need it to go faster. The getlist methods will be called very often and I want to avoid any explicit type checking.

So you want a better interface, because, as you said, passing an unnecessary object to GetList just to figure out its type makes little sense.
You could do something like:
public List<IEntity> GetList<T>() : where T:IEntity
{
if(typeof(T)==typeof(IUndead)) return undedEntities;
// and so on
}
And you'll have to call it like this: GetList<IUndead>();
I think an enum is a better idea here:
enum EntityTypes { Undead, Alive, Object };
public List<IEntity> GetList(EntityTypes entityType) { ... }
It's cleaner and makes more sense to me.
EDIT: Using generics is actually not that simple. Someone could call GetList a Zombie type, which implements IUndead, and then you'll have to check for interface implementations. Someone could even pass you a LiveZombie which implements both IUndead and IAlive. Definitely go with an enum.

How about a better implementation to go with that better interface?
public class EntityBucket
{
public LinkedList<IEntity> Entities;
public IEnumerable<T> GetEntities<T>() where T : IEntity
{
return Entities.OfType<T>();
}
}
List<IUndead> myBrainFinders = bucket.GetEntities<IUndead>().ToList();
With this implementation, the caller better add each item to the right list(s). That was a requirement for your original implementation, so I figure it's no problem.
public class EntityBucket
{
Dictionary<Type, List<IEntity>> entities = new Dictionary<Type, List<IEntity>>();
public void Add<T>(T item) where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
entities.Add(tType, new List<IEntity>());
}
entities[tType].Add(item);
}
public List<T> GetList<T>() where T : IEntity
{
Type tType = typeof(T);
if (!entities.ContainsKey(tType))
{
return new List<T>();
}
return entities[tType].Cast<T>().ToList();
}
public List<IEntity> GetAll()
{
return entities.SelectMany(kvp => kvp.Value)
.Distinct() //to remove items added multiple times, or to multiple lists
.ToList();
}
}

How about something like the following?
public LinkedList<IEntity> GetList(Type type) {
if (typeof(IUndead).IsAssignableFrom(type)) return undeadEntities;
if (typeof(ILiving).IsAssignableFrom(type)) return livingEntities;
if (typeof(IObject).IsAssignableFrom(type)) return objects;
}
Then you would call it like this:
var myUndeads = GetList(typeof(IUndead));
var myLivings = GetList(typeof(ILiving));
// etc
The same type of logic could be implemented in your deletes, add, and other methods, and you never need a concrete instance of an object to access them.
The IsAssignableFrom logic handles subclassing just fine (i.e. you could have a CatZombie, which derives from Zombie, which implements IUndead, and this would still work). This means you still only have to create one Delete method, something like the following:
public void Delete(IEntity e, World world) {
if (typeof(IUndead).IsAssignableFrom(type)) undeadEntities.Remove(e);
if (typeof(ILiving).IsAssignableFrom(type)) livingEntities.Remove(e);
if (typeof(IObject).IsAssignableFrom(type)) objects.Remove(e);
}
EDIT: I noticed your comment on zmbq's answer regarding performance; this is definitely NOT fast. If you need high performance, use an enum-style approach. Your code will be more verbose and require more maintenance, but you'll get much better performance.

Seems to me you could just implement a Dictionary
of named LinkedList's and refer to them
by name or enum.
That way adding or removing lists is just an
implementation issue and no separate class to deal with.

Related

Best approach to instantiate object based on string

I'd like to discuss about the best approach (in C#) to instantiate an object based on an input string. Let me explain.
Let'say I have a base class:
public abstract class BaseCar
{
public asbtract int GetEngineID();
//Other stuff...
}
Then I have several implementations of this class, let's say:
public class SportCar : BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
public class OtherCar: BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
And so on...
What I'd like to do is to make a static CarFactory class which has a CreateCar method which accepts a string as a parameter and returns a BaseCar instance, depending on what string you give. The string would be a name of a child class.
For example, if I call CarFactory.CreateCar('SportCar') it should return a SportCar instance.
I know I could use a simple switch statement to check which car has been requested and create a new instance based on that but I don't like this approach for two reasons:
I plan to have a lot of child classes, hard-coding every case wouldn't be too easy to mantain
I plan to implement an inizialization procedure to also give some initial values to the objects I create (using Reflection), so mixing hard-coding and reflection doesn't seem to be a good idea for me.
What I was thinking about is to use the Assembly.CreateInstance from System.Reflection to create an instance of the specified class but since this is the first time I approach this problem, I don't know if there are better ways to do that. Is this a valid approach ?
Considering the input string will come from an XML file, is there a simplier method ? Maybe my issue is already handled in some .NET Assembly which I'm missing.
Here is what I came up with. A generic factory class that automatically registers all types that are a subclass of the given type, and allows you to instantiate them via their name. This is somewhat related to the approach shown in the Java SO question linked by #Achilles in the comments, only that there is no initialisation function associated with the type.
There is no need to maintain an enum/switch combination of all types. It should also be somewhat easily extendable to handle your proposed reflection based initialisation.
static class StringFactory<T> where T : class
{
static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>();
static StringFactory()
{
RegisterAll();
}
static private void RegisterAll()
{
var baseType = typeof(T);
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in domainAssembly.GetTypes()
.Where(t => t.IsSubclassOf(baseType)))
{
s_dKnownTypes.Add(type.Name, type);
}
}
}
static public T Create(string _sTypeName)
{
Type knownType;
if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType))
{
return (T)Activator.CreateInstance(knownType);
}
throw new KeyNotFoundException();
}
}
Assuming the classes of your question exist, you would instantiate a specific car like this:
var car = StringFactory<BaseCar>.Create("SportsCar");
DoSomethingWith(car.EngineID());
Since your question was for a discussion about the best approaches, please consider this only one of them. I have not used this in a production environment, and it is entirely possible that it is the wrong approach to your specific situation. It works well enough to show the general principle, however, and should provide a starting point for further discussion.

Automating an object repository for a game

Hello guys i am having trouble designing an object repository for a game:
class ObjectRepository
{
private readonly LevelType _levelType;
private readonly BaseObject[] _darkForestObjects = new BaseObject[]
{ new DarkForestTreeA(), new DarkForestTreeB(), new DarkForestTreeC() };
private readonly BaseObject[] _lightForestObjects = new BaseObject[]
{ new LightForestTreeA(), new LightForestTreeB(), new LightForestTreeC() };
public ObjectRepository(LevelType lt)
{
_levelType = lt;
}
public BaseObject GetObject(int obj)
{
if (obj < 0 || obj > _darkForestObjects.Length)
{
Debug.LogError("Object does not exist.");
return null;
}
switch (_levelType)
{
case LevelType.DarkForest:
return _darkForestObjects[obj];
case LevelType.LightForest:
return _lightForestObjects[obj];
}
return null;
}
}
public enum LevelType
{
DarkForest = 0,
LightForest = 1,
}
I am searching for a way of automating this class.By automating it i mean that i don't want every time i create a new object deriving from BaseObject to come inside the Repository class and modify arrays.It just doesn't seem natural.Can anybody point me out a suggestion for automation?
I'll take a gander at this, so please let me know if I'm assuming things wrong.
You'll need:
A repository that'll hold your BaseObject-derived instances;
Said repository must be accessible by the BaseObject class;
Whenever a BaseObject is created, it adds itself to the repository.
Now, I've noticed that you hold instances for both dark and light versions of your objects. So I'd additionally suggest a holder class for both light and dark versions of a given 'object'. Like this:
class CompoundObject
{
public BaseObject LightVersion;
public BaseObject DarkVersion;
}
Your repository then hold CompoundObject-derived objects, and instead of BaseObject objects adding themselves at creation time, CompoundObject objects would do it.
Now about Array manipulations, you may be right; it can be somewhat clunky. I'd suggest the adoption of List<CompoundObject> instead of CompoundObject[]. A generic List offer very handy methods like Add and Remove that can streamline your collection manipulation.
If I were you, I would opt for a more generic solution using interfaces.
Considering your example, I assume that you have multiple level types which have their own specific TreeA, TreeB and TreeC implementations.
If I understood right, I would rather use interface for each tree type. Example for TreeA :
public interface ITreeA
{
// any common public members here
}
public class DarkForestTreeA : ITreeA, BaseObject
{
...
}
public class LightForestTreeA : ITreeA, BaseObject
{
...
}
This way, you can ask your repository to provide the ITreeA implementation specific to the level type. Something like :
public T GetObject<T>() // where T could be ITreeA, ITreeB...
{
...
}
So you could call myRepo.GetObject() and get a DarkForestTreeA object if level type is DarkForest for example.
To have this behavior "automated", you could declare all the specific implementations of DarkForest in a unique namespace and then use reflexion to find the class of the namespace that implements ITreeA for example. This may not be very efficient in terms of performance but it gives you great flexibility as you will just have to add new classes in your namespace to have them available from the repository. However, it can also bring other problems (for example, what would happen if you have two classes implementing ITreeA in the same namespace ?).
See Getting all types in a namespace via reflection and Getting all types that implement an interface with C# 3.0 for implementation details.
I have to admit it isn't the simplest solution.
You could consider simpler thing like defining a dictionary for object type (treeA, treeB) and then define a dictionary for each level type mapping the object type to its concrete implementation.
For example :
public enum ObjectType
{
TreeA,
TreeB,
TreeC,
}
Dictionary<ObjectType, Type> DarkForestObjectTypes = new Dictionary<ObjectType, Type>()
{
{ ObjectType.TreeA, typeof(DarkForestTreeA) },
{ ObjectType.TreeB, typeof(DarkForestTreeB) }
...
}
I won't go into more details as this answer looks a bit messy but hopefully it will give you ideas to go on with.

Interacting with a list of generically typed complex objects

I've been searching for awhile to see if anyone was trying to do something close to this and I find a bunch of people trying to interact with a generically typed List. I instead need to interact with a List of complex objects who are generically typed. Here's the current code.
public class RequestBundleItem<T> where T : BaseJsonResponseMessage
{
public T Response { get; private set; }
//intializers - code not needed
public void SetResponse(String jsonResponse)
{
Response = (T)jsonResponse.JsonToObject<T>();
}
}
public class RequestBundleManager
{
private List<RequestBundleItem<T>> BundleItems;
public async Task<List<RequestBundleItem<T>>> ProcessItemsAsync()
{
List<Task<JsonValueEventArgs>> tasks = //create tasks from bundleitems;
for (var i = 0; i < tasks.Count(); i++)
{
Task<JsonValueEventArgs> curTask = tasks[i];
var args = await curTask;
BundleItems[i].SetResponse(args.ValueAsText);
}
return BundleItems;
}
public void AddItem<T>(RequestBundleItem<T> newItem) where T : BaseJsonResponseMessage
{
BundleItems.Add(newItem);
}
}
This line is what's causing the problem
private List<RequestBundleItem<T>> BundleItems;
I don't know how to define this list since T is generic and just needs to implement BaseJsonResponseMessage but I don't want to type the RequestBundleManager itself.
SOLUTION:
I ended up removing the generic from the RequestBundleItem and the consumer is responsible for knowing the response type it needs back.
Make RequestBundleManager generic also:
public class RequestBundleManager<T>
And now you list can be defined with type T. Of course, you have to make sure that the T you use when creating your RequestBundleManger is the same as the one you used for RequestBundleItem, and you list will be homogeneous.
If you want your RequestBundleManager to handle lists with mixed T, then you will need to have RequestBundleItem derive from a base class or else have it implement an interface.
Define the list in your RequestBundleManager like this:
private List<RequestBundleItem<BaseJsonResponseMessage>>
If you don't put a type on the RequestBundleManager, you don't know the specific type of the object inside the list except that it's a BaseJsonResponseMessage. Then it makes sense to just define it like that. It will give you access only to methods defined in BaseJsonResponseMessage though.
If that's not enough, consider defining an interface with all the methods you want to have access to in the RequestBundleManager and put it as a constraint on your type in RequestBundleItem. Something like this:
public class RequestBundleItem<T> where T : BaseJsonResponseMessage, IMyInterface
Then define the list in RequestBundleManager like:
private List<RequestBundleItem<IMyInterface>>

Best pattern to ensure clean code when passing variable frequently within class

Say I have a class with a number of methods - some private, some public.
In one of the public methods, I create a list of objects. This is then used across a number of other methods, which have simply been abstracted out to make code simpler.
So I might have:
public class MyClass
{
public void CreateList()
{
List<MyClass> MyList = new List<MyClass>();
... populate list
DedupeList();
ValidateList();
}
void DedupeList()
{
// do something using MyList
}
void ValidateList()
{
// do something using MyList
}
}
I was wondering what the best approach would be in this instance.
Make the list created by CreateList() a class level variable;
Pass the list a parameter to each of the sub-methods.
Ok, so it depends on what you're trying to achieve and what your classes responsibility is.
If you class represents a real thing which represents part of your domain, and which has state, then your private methods act on that state and I would therefore choose the former.
So
public class Basket
{
private IList<string> Contents;
public Basket()
{
Contents = new Contents();
}
public void Add(string Item)
{
Contents.Add(Item);
}
public void Empty()
{
Contents.Clear();
}
}
This is a trite example, but all I could think of.
If however your class doesn't represent an object with state, such as the calculator below which takes some input, acts on it, and returns it without storing anything, then the latter is better.
That said, there are other considerations, such as keeping code clean and easy to read (should be very high on your priority list), limiting the number of parameters etc being passed (any more than three is often regarded as messy). Example below of when I would elect to pass parameters.
public class InvestmentCalculator
{
pubilc IEnumerable<Stock> CalculateInvestmentValue(IEnumerable<Stock> Stocks)
{
foreach (var stock in stocks)
{
var itemValue = GetSotckValueFromMarket(stock);
stock.UpdateValue(itemValue)
AddProjection(stock);
}
}
public decimal GetStockValueFromMarket(Stock stock)
{
//Do something
}
public decimal AddProjection(Stock stock)
{
//Do something
}
}
I hope that this helps
It depends on meaning of the list. You have to find some answers. Should it be a part of the class or just a temporary variable that should live just along the method call? Is it a part of behavior of the class? How about threading? Even you may rethink if DedupeList and ValidateList methods have to be part of this class or do they deserve a separate class?
I recommend you to read "Implementation Patterns" by Kent Beck and "Clean Code" by Robert C. Martin. There are dozens of very helpful tips for these kind of little but frequent cases.

Cheapest way to make a single object Enumerable?

I have an interface function that returns an IEnumerable<MyObject> collection.
Some of my classes only use one hardcoded instance of MyObject, but still need to implement the interface.
Currently I am just creating a System.Array like so:
public class SomeClass : IMyInterface
{
private MyObject _myObject;
public IEnumerable<MyObject> IMyInterface.GetMyObjects()
{
return new MyObject[] { _myObject };
}
}
I just wondered if there was a more efficient way, or any magic to cast the object itself?
You may just...
public IEnumerable<MyObject> IMyInterface.GetMyObjects()
{
yield return _myObject;
}
...but consider that this will cause the compiler to generate a whole state machine class for it to work. If that sounds cheap for you, OK. Otherwise, the array solution looks fine. You may want to pre-create the array if there's no problem in reusing its instance.
I believe the following should be considerably cheap:
public IEnumerable<MyObject> IMyInterface.GetMyObjects()
{
return new MyObject[1] { _myObject };
}

Categories

Resources