【问题标题】:Declaring anonymous type as array correctly to keep scope正确地将匿名类型声明为数组以保持范围
【发布时间】:2013-01-15 23:11:30
【问题描述】:

我要做的就是正确声明var place,因此一旦我进入foreach 循环,它仍然在范围内。我假设我需要在 if 声明 connections 之前声明它。这是一个正确的假设吗?如果是,我该如何声明?谢谢!

using (var db = new DataClasses1DataContext())
        {
            if (connections == "Connections")
            {
                var place = (from v in db.pdx_aparts
                             where v.Latitude != null && v.Region == region && v.WD_Connect >= 1
                             select new
                             {
                                 locName = v.Apartment_complex.Trim().Replace(@"""", ""),
                                 latitude = v.Latitude,
                                 longitude = v.Longitude
                             }).Distinct().ToArray();
            }
            else
            {
                var place = (from v in db.pdx_aparts
                             where v.Latitude != null && v.Region == region &&    ((v.WD_Connect == null) || (v.WD_Connect == 0))
                             select new
                             {
                                 locName = v.Apartment_complex.Trim().Replace(@"""", ""),
                                 latitude = v.Latitude,
                                 longitude = v.Longitude
                             }).Distinct().ToArray();

            }

            foreach (var result in place)
            ....

【问题讨论】:

  • 您可以将if 折叠到where 中,并且只有一个查询?我不认为你可以在分配给它之前声明一个匿名类型的变量。
  • @Blorgbeard 可能会阻止 SQL Server 使用索引。取决于 OP 架构。
  • @usr 我正在使用索引。感谢您注意到

标签: c# linq c#-4.0


【解决方案1】:

您可以创建一个包含单个条目的数组,该条目的值稍后会被忽略:

// Note: names *and types* must match the ones you use later on.
var place = new[] { new { locName = "", latitude = 0.0, longitude = 0.0 } };
if (connections = "Connections")
{
    // Note: not a variable declaration
    place = ...;
}
else
{
    place = ...;
}

之所以有效,是因为每次使用具有相同名称和类型的属性的匿名类型,以相同的顺序,都将使用相同的具体类型。

我认为最好让代码在它需要的部分有所不同:

var query = v.db.pdx_aparts.Where(v => v.Latitude != null && v.Region == region);
query = connections == "Connections"
    ? query.Where(v => v.WD_Connect >= 1)
    : query.Where(v => v.WD_Connect == null || v.WD_Connect == 0);
var places = query.Select(v =>  new
                          {
                              locName = v.Apartment_complex
                                         .Trim()
                                         .Replace("\"", ""),
                              latitude = v.Latitude,
                              longitude = v.Longitude
                          })
                  .Distinct()
                  .ToArray();

这里更容易看出,依赖于connections 值的only 部分是查询中处理WD_Connect 的部分。

【讨论】:

    【解决方案2】:

    您可以将if 转换为?:

    var place = connections == "Connections" ? monsterQuery1 : monsterQuery2;
    

    我认为这不是一个好的解决方案,因为您的查询太大(不可读)。

    如果你引入一个你使用的命名类来代替匿名类型会更好。 R# 在“灯泡菜单”重构中为您做到这一点。

    【讨论】:

    • 更改为使用命名类不会本身减少大查询。有更好的方法来处理不需要命名类的部分。
    • @JonSkeet 我同意,你的回答更好。更全面。
    【解决方案3】:

    您可以只使用 1 查询,因为它们几乎相同,只需在 where 子句中添加额外的条件

    var place = (from v in db.pdx_aparts
                 where v.Latitude != null && v.Region == region 
                 &&  connections == "Connections" 
                 ? v.WD_Connect >= 1 
                 : ((v.WD_Connect == null) || (v.WD_Connect == 0))
                 select new
                 {
                     locName = v.Apartment_complex.Trim().Replace(@"""", ""),
                     latitude = v.Latitude,
                     longitude = v.Longitude
                 }).Distinct().ToArray();
    
    
     foreach (var result in place)
     ....
    

    【讨论】:

    • 这可能会阻止 SQL Server 使用索引。取决于 OP 架构。它会执行,但性能可能会更差。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多