【问题标题】:Declaring an empty Queryable?声明一个空的 Queryable?
【发布时间】:2012-06-11 12:50:51
【问题描述】:

如何声明这样的变量?

            var rData = from nc in ctx.NEWSLETTER_CLIENTS
                        join ni in ctx.NEWSLETTER_INDICES on nc.INDEX_NUM 
                                                          equals ni.INDEX_NUM
                        select new
                        {
                            ClientID = nc.CLIENT_ID,
                            Email = nc.CLIENT_EMAIL_ADDRESS,
                            Index = nc.INDEX_NUM,
                            MainClass = ni.MAIN_CLASS,
                            SubClass = ni.SUB_CLASS,
                            App1 = ni.VALUE_1,
                            App2 = ni.VALUE_2,
                            App3 = ni.VALUE_3,
                            App4 = ni.VALUE_4
                        };

        // Now I need to declare on a variable named fData under the function scope,
        // so I can later use it:

        var fData = ...; //What do I declare here?

        if(x)
            fData = fData.Concat(rData.Where(u => ...));
        if(y)
            fData = fData.Concat(rData.Where(u => ...));
        // etc

【问题讨论】:

  • 在这种情况下,您可以使用ternary operator 将其重构为一个作业,但这样的问题仍然很有趣。

标签: c# linq iqueryable


【解决方案1】:
IQueryable<type of p> fData = null;

如果你想稍后使用查询(if 之后的 iow):

var fData = Enumerable.Empty<type of p>().AsQueryable();

更新:

现在用于匿名类型:

IQueryable<T> RestOfMethod<T>(IQueryable<T> rData)
{
  var fData = Enumerable.Empty<T>().AsQueryable(); // or = rData;

  if(x)
    fData = fData.Concat(rData.Where(u => ...));
  if(y)
    fData = fData.Concat(rData.Where(u => ...));

  return fData;
}

// original code location
var rData = some query;
var fData = RestOfMethod(rData);

更新 2:

正如所指出的,上述方法实际上不起作用,因为Where 的谓词不知道类型。您可以对其进行更多重构以在参数中包含谓词,例如:

IQueryable<T> RestOfMethod<T>(IQueryable<T> rData, 
  Expression<Func<T,bool>> pred1,
  Expression<Func<T,bool>> pred2) 
{ ... }

更新 3:(也许是 hacky)

var fData = rData.Take(0); // should be cheap. 

【讨论】:

  • 谢谢你,它确实有帮助,请参阅我的编辑以获得澄清
  • @Shai:对于匿名类型,这并不容易,但可以通过对方法的其余部分进行一点重构来部分完成。
  • @Shai:我在之前的评论中添加了一个示例。
  • 谢谢 - 但这不会编译,因为 RestOfMethod 不知道 u 包含哪些成员...
  • @Shai:你是对的,再重构它会很乱:(
【解决方案2】:

您可以将其声明为 IQueryable 而不是 var。您不能将 fData 声明为 var 的原因是“var”需要在声明期间推断类型。如果你提前知道类型,你可以声明它就好了。

IQueryable fData = null;

更好的是,如果您知道 p 的类型,则可以使用 IQueryable 的泛型形式使其成为强类型:

IQueryable<type-of-p> fdata = null;

请注意,这会分配 null!如果你尝试使用它,你会得到一个空引用异常。如果你真的想要一个 empty 可查询对象,那么使用 leppie 的建议,并使用 Enumerable.Empty().AsQueryable() 方法链创建一个空集合。

【讨论】:

  • 除非您将 p 转换为对象,否则我非常怀疑它是否会起作用(甚至可以编译)。
  • 您不需要将 p 转换为对象;一切都是 .NET 可以隐式转换为对象。
  • 由于协方差,它可能在 .NET 4 下工作,但在 .NET 3.5 上肯定会失败。
【解决方案3】:

好吧,以下解决方案可能不好(甚至包含一些不需要的开销),但是,它可以工作:

var fData = from p in rData
            where 0 == 1
            select p;

if(x)
    fData = fData.Concat(rData.Where(u => ...));
if(y)
    fData = fData.Concat(rData.Where(u => ...));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多