Throw different objects and call a method on one line?

I have a 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 something like this is possible?

I want to do this on one line. Here is what I mean:

 (Enemy)o => Update(time, player); 

I know this is stupid, but I need something like that. A method that has a player as a parameter is unique to an Enemy object. I need to take it apart.

+5
source share
6 answers

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 below, 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 fewer lines of code, but you do twice.

You can use only once:

 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); } } 
+7
source

Try the following:

 ((Enemy)o).Update(time, player); 

Be aware of a possible Null Reference Exception if you have not checked the type of this object. Everything is fine in your code.

+3
source

You can replace these two lines with one line as follows:

 else if(o is Enemy) { ((Enemy)o).Update(time, player); } 
+3
source

You call the function this way:

 var a = ((Portal)o).Interact(ref player, player.Interact); 

therefore, type a will be the returned Interact type, but in the context of your code this does not really matter.

+2
source

To go further than the other answer, you can use a template.

First create the IVisitorClient and IVisitor .

 interface IVisitorClient { Accept(IVisitor visitor); } interface IVisitor { Visit(SceneObject o); // here the types of your objects Visit(Enemy e); Visit(Portal p); } 

Make your other IVisitorClient object.

 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 create an update that implements 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); } 
+1
source

Or do it in such a way as to avoid double-clicking ...

 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); } } } 
0
source

Source: https://habr.com/ru/post/1262686/


All Articles