【问题标题】:Lambda Expression for FirstOrDefault with two parametersFirstOrDefault 的 Lambda 表达式,带有两个参数
【发布时间】:2022-01-21 13:16:37
【问题描述】:

我有一个传递给 First()FirstOrDefault() 调用的 lambda 表达式。

我想在 lambda 执行时动态注入一个参数值。

这是我现在的破解代码;它在运行的意义上“有效”。

ObservableCollection<T> Rows { get; set; }

T currentRow = Rows[0];
Template r = (Template)(object)currentRow;

Func<T, bool> p = e => ((Template)(object)e).TemplateId.Equals(r.TemplateId);

var firstRow = Rows.First(p);

我想要一些能正确处理通用 T 的东西

public class Model<T>
{
    public ObservableCollection<T> Rows { get; set; } = {add rows here}
    
    public Func<T, T, bool> Lambda { get; set; }
    
    public T CompareRow {get; set;} // assume not null
    public T SelectedRow { get; set; }

    public GetRow()
    {
       T currentRow = CompareRow; 

       // First extension takes a lambda expression of Func<T,bool>
       // SOMEHOW inject the runtime value of currentRow into lambda
       // to convert Func<T, T, bool> to Func<T, bool>

       var firstRow = Rows.First(Lambda);  // get first row that matches Lamda

       SelectedRow = firstRow;
    }
} 

public class MyModel: Model<Entity>
{
    public void MyModel()  : base()
    {
       // define the lambda expression with the concrete type of <Entity>
       // each <Entity> type has different fields;
       // so want to define a Lambda in the concrete class to validate the fields,
       // but one that can be used in the generic base class.

       Func<Entity, Entity, bool> p = (e,r) => e.TemplateId.Equals(r.TemplateId);
       Lambda = p;
    }

    public SetRow()  // called from somewhere
    {
       CompareRow = Rows.Last();  // assume Rows is not empty
    }

    public GetRow()
    {
        base.GetRow();
    }
}

我找到了这些……

[https://stackoverflow.com/questions/16985310/convert-expressionfunct-t-bool-to-expressionfunct-bool] (这里面有额外的代码......所以这可以改进吗?)

[https://stackoverflow.com/questions/21922214/create-dynamic-linq-expression-for-select-with-firstordefault-inside] (这是特定于创建“选择” lambda)。

[https://www.codementor.io/@juliandambrosio/how-to-use-expression-trees-to-build-dynamic-queries-c-xyk1l2l82]

[https://stackoverflow.com/questions/63172233/dynamic-firstordefault-predicate-expression]

另外:如果有不同的调用方式

var firstRow = Rows.First(Lambda);

直截了当,欢迎提出建议。

【问题讨论】:

  • 这是一个 lambda 表达式(是的,这是“d”之前的“b”) - 不是“lamda” ....

标签: c# linq


【解决方案1】:

您可以通过这种方式调用您的 Lambda 函数。

public GetRow()
{
   T currentRow = CompareRow; 
   var firstRow = Rows.First(row => Lambda(row, CompareRow));  // get first row that matches Lambda

   SelectedRow = firstRow;
}

这里是另一个使用string参数的例子:

List<string> names = new() { "Alice", "Bob", "Charlie" };
string nameToMatch = "Alice";
Func<string, string, bool> Lambda = (left, right) => left.GetHashCode() == right.GetHashCode();
var alice = names.First(name => Lambda(name, nameToMatch));
Console.WriteLine($"Hi {alice}");

您在设置 Lambda 时可能会遇到一些问题。类型看起来错误 Func&lt;Entity, Entity, bool&gt; 不是 Func&lt;T, T, bool&gt; 因为没有限制 T 是什么类型。

您可能需要考虑在T 上添加一个约束,可能是这样的:

public class Model<T>
   where T : Entity
{
    public Func<Entity, Entity, bool> Lambda { get; set; }
}

【讨论】:

  • 1 - 是的,我实际上正在使用 where 子句;我没有包含在示例代码中。 2 你的第一个建议似乎奏效了......现在测试一下......(绝对比我正在阅读的其他一些解决方案更简洁的代码。)
猜你喜欢
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多