如何将 Predicate 转换为到表达式>与起订量一起使用?

发布于 2024-09-28 15:04:04 字数 689 浏览 2 评论 0 原文

请帮助这个 Linq 新手!

我正在测试的类中创建一个列表,我想使用 Moq 来检查结果。

我可以轻松地组合一个谓词来检查列表的结果。那么我该如何将该谓词变成表达式呢?

var myList = new List<int> {1, 2, 3};

Predicate<List<int>> myPredicate = (list) => 
                  {
                      return list.Count == 3; // amongst other stuff
                  };

// ... do my stuff

myMock.Verify(m => m.DidStuffWith(It.Is<List<int>>( ??? )));

???如果您能够了解这么多泛型,则需要是一个 Expression>> 。我找到了以相反的方式执行此操作并将表达式编译为谓词的答案。不过,它们并没有帮助我更好地理解 Linq。

编辑:我已经让它与方法一起工作了;带有表情;我只是想知道是否有任何方法可以使用带有 body 的 lambda 来实现这一点 - 如果没有,为什么不呢?

Please help this Linq newbie!

I'm creating a list inside my class under test, and I would like to use Moq to check the results.

I can easily put together a Predicate which checks the results of the list. How do I then make that Predicate into an Expression?

var myList = new List<int> {1, 2, 3};

Predicate<List<int>> myPredicate = (list) => 
                  {
                      return list.Count == 3; // amongst other stuff
                  };

// ... do my stuff

myMock.Verify(m => m.DidStuffWith(It.Is<List<int>>( ??? )));

??? needs to be an Expression<Predicate<List<int>>> if you can get your head round that many generics. I've found answers which do this the other way round and compile an Expression into a Predicate. They're not helping me understand Linq any better, though.

EDIT: I've got it working with methods; with expressions; I would just like to know if there's any way to do it with a lambda with a body - and if not, why not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟花肆意 2024-10-05 15:04:04

更改:

Predicate<List<int>> myPredicate = (list) => list.Count == 3;

至:

Expression<Predicate<List<int>>> myPredicate = (list) => list.Count == 3;

编译器为您施展魔法。有一些警告1,任何仅处理表达式(无块)的 lambda 都可以通过包装委托类型(在本例中为 Predicate<;列表>)和表达式<>。正如您所指出的,您可以通过调用 myPredicate.Compile() 再次反转它。

1 例如,异步 lambda(即 async () =>await Task.Delay(1);)无法转换为表达式树。

更新:如果编译器包含语句,您就无法使用编译器来获得所需的表达式树。您必须使用 Expression 中的静态方法自行构建表达式树(需要做更多工作)。 (Expression.BlockExpression.IfThen 等)

Change:

Predicate<List<int>> myPredicate = (list) => list.Count == 3;

To:

Expression<Predicate<List<int>>> myPredicate = (list) => list.Count == 3;

The compiler does the magic for you. With some caveats1, any lambda dealing only with expressions (no blocks) can be converted into an expression tree by wrapping the delegate type (in this case Predicate<List<int>>) with Expression<>. As you noted, you could then invert it yet again by calling myPredicate.Compile().

1 For example, async lambdas (i.e. async () => await Task.Delay(1);) cannot be converted to an expression tree.

Update: You simply cannot use the compiler to arrive at the expression tree you want if it includes statements. You'll have to build up the expression tree yourself (a lot more work) using the static methods in Expression. (Expression.Block, Expression.IfThen, etc.)

旧情别恋 2024-10-05 15:04:04

Kirk Woll 的回答直接解决了您的问题,但请考虑以下事实:您可以在 void 方法的 Setup 上使用 Callback 方法来处理调用时传入的参数。这对我来说更有意义,因为无论如何你已经必须构建一个方法来验证列表;它还为您提供列表的本地副本。

//what is this list used for?
var myList = new List<int> {1, 2, 3};

List<int> listWithWhichStuffWasDone = null;
//other setup

myMock.Setup(m => m.DoStuffWith(It.IsAny<List<int>>()).
    Callback<List<int>>(l => listWithWhichStufFWasDone = l);

objectUnderTest.MethodUnderTest();

myMock.Verify(m => m.DoStuffWith(It.IsAny<List<int>>()));
Validate(listWithWhichStuffWasDone);

Kirk Woll's answer directly addresses your question, but consider the fact that you can use the Callback method on a Setup of a void method to handle the parameters which were passed in on invocation. This makes more sense to me since you're already having to build a method to validate the list anyway; it also gives you a local copy of the list.

//what is this list used for?
var myList = new List<int> {1, 2, 3};

List<int> listWithWhichStuffWasDone = null;
//other setup

myMock.Setup(m => m.DoStuffWith(It.IsAny<List<int>>()).
    Callback<List<int>>(l => listWithWhichStufFWasDone = l);

objectUnderTest.MethodUnderTest();

myMock.Verify(m => m.DoStuffWith(It.IsAny<List<int>>()));
Validate(listWithWhichStuffWasDone);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文