c# - 如何使用 Func<T,Q> 在 Linq 中指定 .NET 匿名对象返回类型?

标签 c# linq anonymous-types

如何为匿名对象指定Func 签名?

new Func<DataSet, **IEnumerable<int>>**

我在 Func 声明中指定为 IEnumerable<> 的返回类型有问题

我从表达式中得到的错误是

Cannot convert expression type 'System.Collections.Generic.IEnumerable<{ParentNodeId:int}>' to returnt ype 'System.Collections.Generic.IEnumerable'

如何在 func 中指定 IEnumerable<{ParentNodeId:int}>

    public int GetCachedRootNodeId(IList<int> fromNodeIds, int forNodeId)
    {
        var result = forNodeId;

        const string spName = "spFetchAllParentNodeIDs";
        using (var ds = _df.ExecuteDatasetParamArray(_ConnectionString, spName, forNodeId))
        {
            if (DataAccessUtil.DataSetIsEmpty(ds)) return result;

            var orderByLevelDesc = new Func<DataSet, IEnumerable<int>>(resultSet =>
                from DataRow row in DataAccessUtil.GetFirstTableRows(resultSet) 
                orderby DataAccessUtil.GetInt32(row, "Level") descending 
                select new { ParentNodeId = DataAccessUtil.GetInt32(row, "ParentNodeID") });

            //// Get top-most parent's node ID first (higher the level, the more top-most the parent is)
            //var query = from DataRow row in DataAccessUtil.GetFirstTableRows(ds)
            //            orderby DataAccessUtil.GetInt32(row, "Level") descending
            //            select new { ParentNodeId = DataAccessUtil.GetInt32(row, "ParentNodeID") };
            //foreach (var nodeInfo in query)
            foreach (var nodeInfo in orderByLevelDesc(ds))
            {
                if (fromNodeIds.Contains(nodeInfo.ParentNodeId))
                    return nodeInfo.ParentNodeId;
            }
        }

        return result;
    }

顺便说一句,我本可以使用注释代码“query”并完成它。 但是在看了这个答案之后想要更具表现力并尝试一些新的东西 Why doesn't C# have lexically nested functions?

编辑:最终结果

    public int GetCachedRootNodeId(IList<int> fromNodeIds, int forNodeId)
    {
        var result = forNodeId;

        const string spName = "spFetchAllParentNodeIDs";
        using (var ds = _df.ExecuteDatasetParamArray(_ConnectionString, spName, forNodeId))
        {
            if (DataAccessUtil.DataSetIsEmpty(ds)) return result;

            var orderParentNodeIDByLevelDesc = new Func<DataSet, IEnumerable<int>>(resultSet =>
                from DataRow row in DataAccessUtil.GetFirstTableRows(resultSet) 
                orderby DataAccessUtil.GetInt32(row, "Level") descending
                select DataAccessUtil.GetInt32(row, "ParentNodeID"));

            foreach (var parentNodeId in orderParentNodeIDByLevelDesc(ds))
            {
                if (fromNodeIds.Contains(parentNodeId))
                    return parentNodeId;
            }
        }

        return result;
    }

最佳答案

这里有一个想法 - 调用一个静态方法并让类型推断来完成它:

public static Func<T, TResult> FuncOf(Func<T, TResult> func)
{
    return func;
}

然后调用它:

var orderByLevelDesc = FuncOf(resultSet =>
    from DataRow row in DataAccessUtil.GetFirstTableRows(resultSet) 
    orderby DataAccessUtil.GetInt32(row, "Level") descending 
    select new { ParentNodeId = DataAccessUtil.GetInt32(row, "ParentNodeID")
    });

基本上你只需要“Func”部分来告诉编译器它需要将 lambda 表达式转换为委托(delegate)而不是表达式,以及委托(delegate)的类型。它应该能够计算出给定 FuncOf 签名的类型。

无论如何,值得一试。

顺便说一下,我发现您的注释掉的版本更容易理解。为什么要引入一个额外的功能?或者您是否计划将其作为局部变量(这更有意义,但您不能使用var)?或者可能是在循环外部而不是内部声明的局部变量?

关于c# - 如何使用 Func<T,Q> 在 Linq 中指定 .NET 匿名对象返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/596465/

相关文章:

c# - Linq - 在可能没有记录的表上使用左连接

c# - 将 linq 连接的左侧或右侧填充为相同的行数

c# - 将 Dictionary<string, object> 转换为匿名对象?

c# - 空传播 - 第二次空检查

c# - 将关键字等效项从 Java 更新为 C#

c# - Nullable<> 作为 ViewPage 的 TModel

javascript - 命名匿名函数

c# - Entity Framework 核心包含过滤器

c# - 没有从 'ApplicationDbContext' 到 'System.Data.Linq.DataContext' 的隐式引用转换

c# - 使用任意数量的属性初始化新的匿名对象的表达式树