New to LINQ: Is this the right place to use LINQ?

First off, I'm new to LINQ, so I really don't know what it is. I try to use it in some code per minute, and according to my diagnostics, it is about as fast as using a for loop in the same way. However, I'm not sure how much this will scale, since the lists I work with can grow significantly.

I use LINQ as part of the collision detection function (which still works), and I use it to select a list only for those related to checks.

Here is the LINQ version:

partial class Actor {
    public virtual bool checkActorsForCollision(Vector2 toCheck) {
        Vector2 floored=new Vector2((int)toCheck.X, (int)toCheck.Y);

        if(!causingCollision) // skip if this actor doesn't collide
            return false;

        foreach(
            Actor actor in
            from a in GamePlay.actors
            where a.causingCollision==true&&a.isAlive
            select a
            )
            if( // ignore offscreen collisions, we don't care about them
                (actor.location.X>GamePlay.onScreenMinimum.X)
                &&
                (actor.location.Y>GamePlay.onScreenMinimum.Y)
                &&
                (actor.location.X<GamePlay.onScreenMaximum.X)
                &&
                (actor.location.Y<GamePlay.onScreenMaximum.Y)
                )
                if(actor!=this) { // ignore collisions with self
                    Vector2 actorfloor=new Vector2((int)actor.location.X, (int)actor.location.Y);

                    if((floored.X==actorfloor.X)&&(floored.Y==actorfloor.Y))
                        return true;
                }

        return false;
    }
}

This is my previous method:

partial class Actor {
    public virtual bool checkActorsForCollision(Vector2 toCheck) {
        Vector2 floored=new Vector2((int)toCheck.X, (int)toCheck.Y);

        if(!causingCollision) // skip if this actor doesn't collide
            return false;

        for(int i=0; i<GamePlay.actors.Count; i++)
            if( // ignore offscreen collisions, we don't care about them
                (GamePlay.actors[i].location.X>GamePlay.onScreenMinimum.X)
                &&
                (GamePlay.actors[i].location.Y>GamePlay.onScreenMinimum.Y)
                &&
                (GamePlay.actors[i].location.X<GamePlay.onScreenMaximum.X)
                &&
                (GamePlay.actors[i].location.Y<GamePlay.onScreenMaximum.Y)
                )
                if( // ignore collisions with self
                    (GamePlay.actors[i].isAlive)
                    &&
                    (GamePlay.actors[i]!=this)
                    &&
                    (GamePlay.actors[i].causingCollision)
                    ) {
                    Vector2 actorfloor=
                        new Vector2(
                            (int)GamePlay.actors[i].location.X,
                            (int)GamePlay.actors[i].location.Y
                            );

                    if((floored.X==actorfloor.X)&&(floored.Y==actorfloor.Y))
                        return true;
                }

        return false;
    }
}

( ), , , , .

+5
5

; , , , :

-, " ". , GamePlay. , : (1) (2) . , , .

-, . , . , , .

-, .

-, . "IsFoo" "HasFoo". , .

-, .

-, somebool == true. somebool. " , bool ", .

, :

public virtual bool HasCollisionWithAnyActor(Vector2 toCheck)
{
    // "Easy out": if this actor does not cause collisions then
    // we know that it is not colliding with any actor.
    if (!causingCollision)
      return false;

    Vector2 floored = toCheck.Floor();

    var collidingActors = 
      from actor in GamePlay.actors
      where actor != this
      where actor.causingCollision
      where actor.isAlive
      where GamePlay.IsOnScreen(actor.location)
      where actor.location.Floor() == floored
      select actor;

    return collidingActors.Any();
}

, , ! X Y. , scutwork. : , - , .

+11

LINQ , GamePlay.actors[i]. actors for.

public virtual bool checkActorsForCollision(Vector2 toCheck)
{
    Vector2 floored = new Vector2((int) toCheck.X, (int) toCheck.Y);

    if (!causingCollision) // skip if this actor doesn't collide
    return false;

    for (int i = 0; i < GamePlay.actors.Count; i++)
    {
        Actor actor = GamePlay.actors[i];
        // ignore offscreen collisions, we don't care about them
        if ((actor.location.X > GamePlay.onScreenMinimum.X) &&
            (actor.location.Y > GamePlay.onScreenMinimum.Y) &&
            (actor.location.X < GamePlay.onScreenMaximum.X) &&
            (actor.location.Y < GamePlay.onScreenMaximum.Y))
        {

            if ((actor.isAlive) && (actor != this) &&
                (actor.causingCollision)) // ignore collisions with self
            {
                Vector2 actorfloor =
                  new Vector2((int) actor.location.X,
                              (int) actor.location.Y);
                if ((floored.X == actorfloor.X) &&
                    (floored.Y == actorfloor.Y))
                  return true;
            }
        }
    }
    return false;
}

LINQ . , for. ( LINQ for). , LINQ, .

LINQ:

return (from actor in GamePlay.actors
        where actor.causingCollision && a.isAlive
        where actor != this
        where (actor.location.X > GamePlay.onScreenMinimum.X) &&
              (actor.location.Y > GamePlay.onScreenMinimum.Y) &&
              (actor.location.X < GamePlay.onScreenMaximum.X) &&
              (actor.location.Y < GamePlay.onScreenMaximum.Y)
        select new Vector2((int)actor.location.X,
                           (int)actor.location.Y)).Any(actorfloor => (floored.X == actorfloor.X) &&
                                                                     (floored.Y == actorfloor.Y));
+2

LINQ . , , Diagnostics.StopWatch

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.elapsedticks.aspx

, LINQ, .

return (from actor in (from a in GamePlay.actors
                                   where a.CausingCollision == true && a.IsAlive
                                   select a)
                    where (actor.location.X > GamePlay.onScreenMinimum.X) && (actor.location.Y > GamePlay.onScreenMinimum.Y) && (actor.location.X < GamePlay.onScreenMaximum.X) && (actor.location.Y < GamePlay.onScreenMaximum.Y)
                    where actor != this
                    select new Vector2((int) actor.location.X, (int) actor.location.Y)).Any(actorfloor => (floored.X == actorfloor.X) && (floored.Y == actorfloor.Y));
+1

, , , LINQ if/else.

FYI: LINQ-Methodes , :

foreach(Actor actor in from a in GamePlay.actors
                           where a.causingCollision == true 
                           && a.isAlive
                           select a)
{
  //...
}

:

foreach(Actor actor in GamePlay.actors.Where( a => a.causingCollision == true && a.isAlive))
{
  //...
}

return in both cases is IEnumerable filtered. My personal opinion is that methods are easier to read and understand. In "Where" (...) you can put the full lambda expression to fully select only those you want.

+1
source

LINQ is pretty optimized, and its output is the same as manually writing your fors. By the way, extension methods are much more readable. Your example would look like this:

public virtual bool checkActorsForCollision(Vector2 toCheck)
{
    Vector2 floored = new Vector2((int)toCheck.X, (int)toCheck.Y);

    // skip if this actor doesn't collide
    if (!causingCollision)
    {
        return false;
    }

    return GamePlay.actors.Where( actor =>    
            (actor.causingCollision == true) 
            && actor.isAlive
            // ignore offscreen collisions, we don't care about them
            && (actor.location.X > GamePlay.onScreenMinimum.X) 
            && (actor.location.Y > GamePlay.onScreenMinimum.Y)          
            && (actor.location.X < GamePlay.onScreenMaximum.X) 
            && (actor.location.Y < GamePlay.onScreenMaximum.Y)
            // ignore collisions with self
            && (actor != this) )
        .Select( actor => new Vector2((int)actor.location.X, (int)actor.location.Y) )
        .Any( actorFloor => 
            (floored.X == actorfloor.X) 
            && (floored.Y == actorfloor.Y));
}

There is no reason not to use LINQ for "performance reasons" if you have not profiled your application.

+1
source

All Articles