I have an Array of an interface named iBlocks which contains objects of more than a single class(that all implement the iBlocks interface). I'm wondering if it is possible, or how else to handle the situation in which i need to call methods not covered by the interface for all objects of a certain class within this array.
For example:
iBlocks = new iBlocks[1];
iBlocks[0] = new greenBlock();
iBlocks[1] = new yellowBlock();
foreach (greenBlock in iBlocks)
{
greenBlock.doStuff()
}
Where doStuff() is a method not defined in the interface, as it has no use in the yellowBlock class. The actual interface works brilliantly as greenBlock and yellowBlock have tons of common features. However, there are special aspects of each class i would like to still access without creating an entirely separate array for each object type.
Thanks in advance!
You can use the as operator.
foreach (var block in iBlocks)
{
var green = block as greenBlock;
if (green != null)
green.doStuff()
}
Or in LINQ
foreach (var green in iBlocks.OfType<greenBlock>())
{
green.doStuff()
}
Related
I am attempting to iterate through the members of a list which implement a particular interface, called ImplementsGraphics and then call the method GetModels and add the return result to a list.
However, whenever I attempt to iterate through my objects, and perform the casting operation, I appear to be overwriting the same reference during my iteration. I have deduced that my problem is something to do with where, when and how I am instantiating my variables, but I can not decipher exactly what the intended behavior is.
I've tried numerous permutations of the following code:
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors.Where(n=>n is ImplementsGraphics))
{
var graphicActor = (ImplementsGraphics)actor;
models.AddRange(graphicActor.GetModels());
}
return models;
}
The problem line is var graphicActor = (ImplementsGraphics)actor; but I don't know how to write it such that declaring graphicsActor does not overwrite the existing instances of it stored in models.
Before my first several rounds of troubleshooting, I had
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors)
{
if((ImplementsGraphics)actor != null)
models.AddRange(((ImplementsGraphics)actor).GetModels());
}
return models;
}
Which I expected to work, as I had thought actor was safe across iteration, but apparently not.
Desired Behavior:
Return a list, which is all the return results of GetModels() for ever Actor in RegisteredActors which implements ImplementsGraphics
Actual Behavior:
Returns a list, which is the same return value repeated for each Actor in Registered Actor, which implements ImplementsGraphics.
EDIT:
In the class StaticActor which is a child of Actor and implements ImplementsGraphics its defined as follows:
public List<Model> GetModels()
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = this.Transform.WorldMatrix;
}
}
return new List<Model> { Model };
}
Additonally, I have tried two other approaches which also failed. A for loop, which itereated through all of RegisteredActors, and checked if they implemented ImplementsGraphics, explicitly calling them by their index within RegisteredActors
And a LINQ query, which went
var models = RegisteredActors.Where(n=>n is ImplementsGraphics).SelectMany(n=>((ImplementsGraphics)n).GetModels())
EDIT 2:
The deinfitions of my classes are largely irrelevant, if you want a reproducable example of the behaviour I'm having trouble with, here is a far simpler example.
class MyClass
{
MyOtherClass foo = new MyOtherClass();
int bar = 0;
MyOtherClass GetOtherClass()
{
foo.bar = bar;
return foo;
}
}
class MyOtherClass
{
int bar = 0;
}
List<MyClass> MyCollection = new List<MyClass> {new MyClass(bar = 1), new MyClass(bar = 2), new Myclass(bar = 3)};
List<MyOtherClass> MyOtherCollection = new List<MyOtherClass>();
foreach(MyClass member in MyCollection)
{
MyOtherCollection.Add(member.GetOtherClass());
}
If you were to execute the above code, I expect that the value of MyOtherCollection's bar properties would be: 1, 2, 3
However, the actual result is that:
During the first iteration the values are 1
During the second iteration the values are 2, 2
During the third iteration the values are 3, 3, 3
I would appear, since none of the provided code states, only implies, that you are attempting to reuse a reference to single Model instance to draw multiple objects. Then you are adding multiple references of the same instance to the List.
The solution may be as simple as removing the static modifier from all Model variables and/or container objects.
Normally, the solution would be to create a Deep Copy of the object when it is added to the List, however, it is not directly possible to do this in XNA *1. (not that you would want to)
It would be better to allow each Actor, or StaticActor, object to directly pass its own Model(s) through the GetModels() method in the interface implementation, instead of using the additional class MyOtherClass.
*1. XNA does not expose a public constructor for the Model class. It is possible to do this using reflection. In MonoGame, there is a public Constructor available.
I tend to split my derived Classes and subsequent Lists based on properties like "StaticCollidables","DrawableStaticCollidables" and "DrawableMovingCollidables"...
This technique may require more upfront coding(and therefore is not as "elegant"), but, it is more efficient in terms of memory overhead(8 bytes + (4(32 bit) or 8(64 bit) bytes depending on sizeof(Object)) per List) and CPU overhead(no casting or is).
If you are attempting to reuse the same model, but place it in different locations, use the DrawInstancedPrimitives method using the VertexBuffers contained within each Mesh of the model.
Please comment on which of the above solutions worked for you(if any). If I have missed something please let me know, so I can correct the answer.
I'm studying programming right now and I had to create a snake game.
In the game, there are around 5 possible consumables for the snake and I decided to put every new Consumable in a Consumable array.
Now I wanted to iterate with foreach loops through the array and do something like:
foreach (Apple apple in consumables)
{
renderer.DrawApple(apple);
}
However when there are different objects in the array like an Apple and a SegmentRemover (which is possible, because they inherit from the Consumable class), then the compiler iterates over the SegmentRemover as well and I get an invalid cast exception.
I thought since I'm declaring in the foreach loop that I only want to iterate over Apple objects, that it should work.
Are there any easy ways to get around this? Preferably without things like var or typeof, since I'm not allowed to use these yet.
What you actually want is only those items that are "castable" to the type of Apple. For that use OfType<Apple> (uses linq):
foreach (Apple apple in consumables.OfType<Apple>())
{
renderer.DrawApple(apple);
}
A non linq solution which will do pretty much the same is to use the as operator:
foreach(var item in consumbles)
{
var apple = item as Apple;
if(apple != null)
{
renderer.DrawApple(apple);
}
}
However IMO if all these items are placed in the same list, and as they all inherit from Consumble already, a better design all together, using polymorphisem, is to define for each type of Consumable a draw method as #dasblinkenlight suggested. And have specific implementations for each type. In the case of SegmentRemover it might be an empty implementation and in the Apple it might call the renderer.
You could flip the logic around, letting each consumable draw itself in a renderer:
interface IConsumable {
void draw(Renderer renderer);
}
class Apple : IConsumable {
void draw(Renderer renderer) {
renderer.DrawApple(this);
}
}
class SegmentRemover : IConsumable {
void draw(Renderer renderer) {
renderer.DrawSegmentRemover(this);
}
}
Now your loop can go like this:
foreach (IConsumable consumable in consumables) {
consumable.Draw(renderer);
}
This way you invoke Draw polymorphically on each instance of IConsumable, so the code that gets executed is decided at runtime by the actual class implementing IConsumable interface.
Your consumables is collection, are you trying to get to the collection with an instance of the object that stores the collection? if yes:
Try:
foreach (Apple apple in consumables.consumables)
{
renderer.DrawApple(apple);
}
I'm learning the power of generics in C# in conjunction with NHibernate. I'd like to attempt the following in the pasted code.
In an attempt to do some post processing of N number of NHibernate objects I worked on a utility method leveraging generics to make it applicable to all NHibernate mapping classes we use now, or in the future. It works but I need to hard code each call for each mapping class. This is a pain and will need continuing updating as our schema and mappings change over time.
I do have an ever up-to-date list of all mapping classes by string name through the NHibernate mappings I generate on the fly. If there was a way to use this list of string names to call my generics based method, I'd be super happy.
Can anyone tell me if this is possible? Do I need to find another route?
Thanks so much in advance!!!
public static void ProcessSomeItems()
{
// *************************************************************
// As of now I have to list all classes as such to be processed
// It works but I have to update manually when new mapping classes are created
// *************************************************************
NHibDoSomethingUtil<AspnetMembership>();
NHibDoSomethingUtil<AspnetProfile>();
NHibDoSomethingUtil<AspnetRole>();
NHibDoSomethingUtil<AspnetUser>();
// and so forth...
// I have a up-to-date list of all mappings from "HbmMapping" and can get a list of all in the
// list form as below
List<string> mappingNames = new List<string>();
foreach (string mappingName in mappingNames)
{
Type theType = Type.GetType(mappingName);
// I know I'm getting Types and Generics classes and so forth all jumbled but
// how in the heck would I do something like the below?
NHibDoSomethingUtil<theType>(); // Obviously doesn't compile ;-)
}
}
// Generic method
public static void NHibDoSomethingUtil<T>() where T : class
{
using (ISession session = sourceDBSessionFactory.OpenSession())
{
foreach (dynamic item in new List<T>(session.QueryOver<T>().List()))
{
// Process item;
}
}
}
ecsousa gave great input and I was able to accomplish what I needed with something like the following.
foreach (HbmClass mappingClass in mapping.Items)
{
Console.WriteLine(" -- Discovered Mapping: " + mappingClass.Name);
Type mappingClassType = Type.GetType(mappingClass.Name);
var genericMethod = typeof(Migration).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(mappingClassType);
method.Invoke(null, null);
}
You will need to use Reflection in order to accomplish this. Instead of directly calling NHibDoSomethingUtil, try this:
var genericMethod = typeof(TheClassName).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(theType);
method.Invoke(null, null);
Note that you have to replace TheClassName by the class containing both methods.
Keep in mind the this kind of code is slow, and you should use it very carefully.
Basically I have an arraylist of different types of objects that all have a Draw() function. I want to use a loop to run the draw function of each object. But C# tells me that type "object" doesn't have that function. Any idea's for a lowly n00b?
That Draw method should be defined in an interface:
public interface IDrawable
{
void Draw();
}
All your other classes (with a .Draw method) should implement this interface. And your list should be a List<IDrawable>. Then you can simply invoke the .Draw method on each item as expected:
List<IDrawable> list = new ...;
foreach (var item in list)
{
item.Draw();
}
Unless you're using .NET 1.1, you shouldn't really be using the ArrayList.
If you're talking about UI elements, they should all implement the IDrawable interface. If they're your custom type, you too should implement the IDrawable interface on those classes. You can then use a generic List<T> to store them.
List<IDrawable> objects = new List<IDrawable>();
// Fill the list
// Iterate over each object and call Draw()
foreach(IDrawable obj in objects)
{
obj.Draw();
}
They should all implement an IDrawable interface. and your arraylist will probably want to contain a list of IDrawable rather than object.
If they share a common interface you can cast to that interface.
If the number of types are known and fixed, try to cast to each of the known types with AS operator.
Otherwise you'll have to resort to reflection, something like this
for (i...){
object oneObject = arrayList[i];
Type objectType = oneObject.GetType();
objectType.GetMethod("Draw").Invoke(oneObject, new object[0]);
}
But if you need to resort to reflection that is a huge code smell and should really be avoided.
With an ArrayList all of the elements are stored as the type Object. To call a function defined on antother type you'd first need to cast the members to that type.
class MyType {
public void Draw() {
...
}
}
for (int i = 0; i < arrayList.Count; i++) {
MyType current = (MyType)arrayList[i];
current.Draw();
}
This code only works though if the objects stored in the ArrayList are convertible to MyType. If you're using .Net 2.0 or later then avoid ArrayList entirely and instead use List<MyType>. This is a strongly typed collection and avoids the need for a cast at all.
List<MyType> list = ...;
for (int i = 0; i < list.Count; i++) {
list[i].Draw();
}
If you're using C# 4 or better, you can use the dynamic type for this:
foreach (dynamic obj in arrayList)
obj.Draw();
This will fail at runtime if you have an object whose type lacks a matching Draw() signature.
If you're using an earlier version of C#, you can use reflection.
Having said that, you really ought not to be using ArrayList unless you're forced to by some legacy library. The more idiomatic solution, as others suggest, is to have an IDrawable interface and a List<IDrawable>.
if you take a look at the following code, you will (hopefully) see what I am trying to archieve. Basically this code does:
A query for generic storag items (they store their type as string)
If the item is a subclass of SearchCriteria, create the correct instance
Add the instance to the list (SearchCriteria is superclass)
Not very elegant is, of course, the pseudo-switch case, which I would have to update for all different criteria I create.
So, my question, is there a "generic" way to create an instance which is strongly typed using a string as "source" for the type.
I know I can use Reflection to create an instance, but this is of type object, so I would not be able to add it to the list. Oh, just got an idea... Create object using reflection, cast it to supertype (SearchCrit), add to list. Real type should still be the "correct subtype" I hope...
Will try it, and update this post with results. Any better ideas?
Chris
private IList<SearchCriteria> _searchCriteriaAll;
public IList<SearchCriteria> SearchCriteriaAll
{
get
{
if (_searchCriteriaAll == null)
{
_searchCriteriaAll = new List<SearchCriteria>();
var tN = typeof (SearchCriteria).ToString();
foreach (var o in DataStorage.LinkedObjects)
{
if (tN.StartsWith(o.TypeName))
{
if (o.TypeName == typeof(StringSearchCriteria).ToString())
_searchCriteriaAll.Add(new StringSearchCriteria(o));
}
}
}
return _searchCriteriaAll;
}
}
EDIT:
Thanks for the tips, the "correct" way would definitly be the factory pattern. I will look into that. For now, I use this hack, because the subclasses are so small, I dont want a factory for each one.. (and this place is currently the only one with such a "fancy" feature)
private IList<SearchCriteria> _searchCriteriaAll;
public IList<SearchCriteria> SearchCriteriaAll
{
get
{
if (_searchCriteriaAll == null)
{
_searchCriteriaAll = new List<SearchCriteria>();
var tN = typeof (SearchCriteria).ToString();
foreach (var o in DataStorage.LinkedObjects)
{
if (tN.StartsWith(o.TypeName))
{
var newO = Activator.CreateInstance(typeof(SearchCriteria).Assembly.FullName, o.TypeName);
var newCrit = newO.Unwrap() as SearchCriteria;
newCrit.DataStorage = o;
_searchCriteriaAll.Add(newCrit);
}
}
}
return _searchCriteriaAll;
}
}
Generics and reflection don't make good friends. A simpler approach here is to use the non-generic list interface:
_searchCriteriaAll = new List<SearchCriteria>();
IList list = (IList) _searchCriteriaAll;
...
Type type = typeof(SearchCriteria).Assembly.GetType(o.TypeName);
list.Add(Activator.CreateInstance(type));
(where o.TypeName includes the namespace information, but doesn't have to be assembly-qualified)
This is still runtime type-safe (it'll throw at runtime if it is wrong), and still adjusts the same list.
Note also that we only look inside Assembly directly via Assembly.GetType().
I'd say you're looking for the Factory Method Pattern.
There's a C# sample here - the first link explains the pattern better, the second is the right language for you.
It's not entirely clear to me what you are trying to achieve, but you can create a Type from a string like this:
var t = Type.GetType(typeName);
If you want to examine whether it's a proper subtype, you can use the IsAssignableFrom method.