Reputation: 153
I have the code:
foreach(var o in objects)
{
o.Update(time);
if(o is Portal)
{
var a = (Portal)o;
a.Interact(ref player, player.Interact);
}
else if(o is Enemy)
{
var e = (Enemy)o;
e.Update(time, player);
}
}
I don't know if anything like this is possible?
I want to do it in one line. This is what I have in mind:
(Enemy)o => Update(time, player);
I know it's stupid but I want something similar. The method that has player as a parameter is unique to the Enemy object. I have to parse to call it.
Upvotes: 6
Views: 1460
Reputation: 12171
You can make your loop simpler (in case you use C# 6 or higher):
foreach(var o in objects)
{
o.Update(time);
(o as Portal)?.Interact(ref player, player.Interact);
(o as Enemy)?.Update(time, player);
}
For C# 5 or lower you should use:
foreach(var o in objects)
{
o.Update(time);
if (o is Portal)
{
((Portal)o).Interact(ref player, player.Interact);
}
else if(o is Enemy)
{
((Enemy)o).Update(time, player);
}
}
In this case you have less lines of code but you cast two times.
You can cast only one time:
foreach(var o in objects)
{
o.Update(time);
var e = o is Portal;
if (e != null)
{
e.Interact(ref player, player.Interact);
}
else
{
((Enemy)o).Update(time, player);
}
}
Upvotes: 8
Reputation: 8359
To go further than other response, you could use the visitor pattern.
First create a IVisitorClient
and a IVisitor
interface.
interface IVisitorClient
{
Accept(IVisitor visitor);
}
interface IVisitor
{
Visit(SceneObject o); // here the types of your objects
Visit(Enemy e);
Visit(Portal p);
}
Make your different object implement IVisitorClient
.
abstract class SceneObject : IVisitorClient
{
public virtual void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
class Portal : SceneObject
{
...
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
...
}
class Enemy: SceneObject
{
...
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
...
}
Then build an updater that implement IVisitor
:
class UpdaterVisitor : IVisitor
{
readonly Player player;
readonly Time time;
public UpdaterVisitor(Player player, Time time)
{
this.player = player;
this.time = time;
}
public void Visit(SceneObject o)
{
e.Update(time);
}
public void Visit(Enemy e)
{
e.Update(time, player);
}
public void Visit(Portal p)
{
p.Interact(ref player, player.Interact);
}
}
Finally, to update the object, the code will look like this.
var updateVisitor = new UpdaterVisitor(player, time);
foreach(var o in objects)
{
o.Accept(updateVisitor);
}
Upvotes: 1
Reputation: 14672
Or do it this way to avoid the double cast...
foreach(var o in objects)
{
o.Update(time);
Portal p = o as Portal;
if(p != null)
{
p.Interact(ref player, player.Interact);
}
else
{
Enemy e = o as Enemy;
if (e != null)
{
e.Update(time, player);
}
}
}
Upvotes: 0
Reputation: 5787
Try this:
((Enemy)o).Update(time, player);
Remember about possible Null Reference Exception if you didn't check a type of this object. In your code everything is fine.
Upvotes: 4
Reputation: 8991
You can replace those two lines with a single line as follows:
else if(o is Enemy)
{
((Enemy)o).Update(time, player);
}
Upvotes: 4
Reputation: 324
You call the function in that way:
var a = ((Portal)o).Interact(ref player, player.Interact);
so the type of a will be the returned type of Interact, but in context of your code it won't matter much.
Upvotes: 3