Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现IQueryable和ASTs以在游戏中查找实体_C#_Linq_Unity3d_Iqueryable - Fatal编程技术网

C# 实现IQueryable和ASTs以在游戏中查找实体

C# 实现IQueryable和ASTs以在游戏中查找实体,c#,linq,unity3d,iqueryable,C#,Linq,Unity3d,Iqueryable,据我所知,在一些企业C代码中,有一种方法可以将LINQ查询转换为AST,然后使用IQueryable和Expression将其转换为SQL或类似的东西。 这在我看来是这样的: 代码无视DB实现->黑魔法->优化SQL 我想了解黑魔法并将其应用到游戏中。这是我的设想: class Entity { public Vector2 position; } class Chunk { const int CHUNK_SIZE = 16; public Vector2 position;

据我所知,在一些企业C代码中,有一种方法可以将LINQ查询转换为AST,然后使用IQueryable和Expression将其转换为SQL或类似的东西。 这在我看来是这样的:

代码无视DB实现->黑魔法->优化SQL

我想了解黑魔法并将其应用到游戏中。这是我的设想:

class Entity { public Vector2 position; }

class Chunk {
   const int CHUNK_SIZE = 16;
   public Vector2 position;  // chunk position is multiple of CHUNK_SIZE
   public List<Entity> entities;
}

class World {
   public Chunk[,] chunks; // Let's imagine this is a 256x256 array of chunks.
   public IEnumerable<Entity> Entities {
      get {
         return chunks.SelectMany(c => c.entities);
      }
   }
}

class SomewhereElse {
   void NotVerySmartCode() {
      var someArbitraryEntities = world.Entities
         .Where(e => e.position.x > 213 && e.position.x < 247
            && e.position.y > 198 && e.position.y < 212);

      foreach (var e in someArbitraryEntities) { // slooooooow }
   }
}
当NotVerySmartCode查询World.Entities时,枚举器将遍历所有块和所有实体,并对每个块和实体执行Where lambda

很明显,如果Where lambda仅在位置在208 有没有一种方法可以智能地解释LINQ并执行此优化?我能以某种方式实现iQuerable并使用表达式来执行一些黑魔法吗


如果我说的没有任何意义,我很抱歉,但我不明白类似于上面的LINQ查询如何被转换为高效的SQL。

好的,当然我在发布问题半小时后就已经解决了

Func<int, int> addThree = (a) => a + 3; // This compiles to IL
Expression<Func<int, int>> addTwo = (a) => a + 2; // This compiles to an AST
理论上,我们还可以检测其中的模式并对其进行优化。 或者我们可以将它们转换为SQL


基本上,我所缺少的信息是,lambda表达式在分配给表达式时会变成与分配给委托时不同的东西。

我不确定我是否没有正确理解您的意思,或者您是否确实希望对内存中的集合运行SQL。IQueryable用于外部查询,是的,通常是数据库,而不是针对内存中的dataSure进行查询,您可以在优化和代码的尖端之间创建一层间接层,但在我看来,这将导致以后的维护风险。归根结底,您提到的效率之所以会出现,是因为数据库可以利用针对搜索空间定制的索引。因此,您最好将时间花在寻找索引/划分搜索空间的有效方法上,如四叉树等。@CamiloTerevinto不,我不想对内存中的数据运行SQL,但我希望能够操纵表达式树并以这种方式找到优化。@spender好的,是的,没错,我想优化LINQ查询以了解如何存储实体。这不是一个通过四叉树或任何其他数据结构解决的问题,因为在当前设置中,在任何位置快速查找实体都很简单,只需在某个位置查找块并迭代其实体,但这仅在代码知道数据结构的情况下才有效。如果我所知道的只是存在一些实体,而不知道它们存储在块中,那么我将如何优化天真的LINQ查询?我仍然不知道您的方向,但请对您的自我回答投赞成票。@spender谢谢。好的,这个想法是一个程序员如果想要过滤一些数据,在这种情况下,实体,不应该知道数据是以什么方式存储的。理想情况下,他们应该能够为他们想要的数据指定一些要求,系统将确定获取数据的最佳方式。基本上,我想应用数据库的概念。
Debug.Log(addTwo.Body); // (a + 2)
Debug.Log(addTwo.Type); // Func<int, int>
Debug.Log(addTwo.Body.NodeType); // Add
Debug.Log(addTwo.Body is BinaryExpression); // True
Debug.Log(((BinaryExpression)addTwo.Body).Left.NodeType); // Parameter
Debug.Log(((BinaryExpression)addTwo.Body).Right.NodeType); // Constant
Debug.Log(((ConstantExpression)((BinaryExpression)addTwo.Body).Right).Value); // 2
return addTwo.Compile()(2); // 4