Frage

Ich habe eine Erweiterungsmethode mit folgenden Signatur:

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
    ...
}

Ich habe einen Testfall dafür geschrieben, dass die beiden Ausdrücke sind in der Tat kombiniert stellt sicher. Zumindest so, dass der neue Ausdruck I Werke erhalten.

Nun würde Ich mag eine weiteren Test-Fall schreiben, die nur dafür sorgt, dass das Verfahren die Kurzschließen Version von and verwendet. Jede Ahnung, wie ich das tun?

Ich dachte, ich könnte nur so etwas tun:

    [Test]
    public void And_PredicatesAreShortCircuited()
    {
        var predicateNotUsed = true;
        Expression<Func<int, bool>> a = x => false;
        Expression<Func<int, bool>> b = x =>
            {
                predicateNotUsed = false;
                return true;
            };

        var foo = new[] { 1, 2, 3, 4, 5, 6, 7 }
            .Where(a.And(b).Compile())
            .ToArray();

        Assert.That(predicateNotUsed);
    }

Aber ich bekomme eine riesige rote squiggly unter dieser ganzen Aussage Körper für b besagt, dass „Ein Lambda-Ausdruck mit einer Aussage Körper kann nicht auf einen Ausdruck Baum umgewandelt werden“ . So ... alle Optionen? Oder ist dies ein unmögliches Test zu schreiben?

War es hilfreich?

Lösung

Einfacher Vorschlag: einen Referenztyp verwenden, anstatt einen Werttyp, und dereferenzieren es in dem Pfad, den Sie wollen nicht gefolgt. Der Pass in null, und sehen, ob es eine Ausnahme auslöst:)

[Test]
public void And_PredicatesAreShortCircuited()
{
    Expression<Func<string, bool>> a = x => false;
    Expression<Func<string, bool>> b = x => x.Length > 10;

    var foo = new[] { null, null }
        .Where(a.And(b).Compile())
        .ToArray();
}

Eine andere Alternative wäre, eine Neben Bewirkung Funktion an den Eingangsdaten zu verwenden (beispielsweise in etwas übergeben, die durch den Ausdruck Baum geändert werden können), aber ich denke, die oben werden wahrscheinlich der einfachste Ansatz sein:)

Oder eine andere Idee:

public T NonVoidFail(T x)
{
    Assert.Fail("I shouldn't be called");
    return x; // Will never happen
}

Dann:

[Test]
public void And_PredicatesAreShortCircuited()
{
    Expression<Func<int, bool>> a = x => false;
    Expression<Func<int, bool>> b = x => NonVoidFail(x);

    var foo = new[] { 1, 2, 3, 4, 5, 6, 7 }
        .Where(a.And(b).Compile())
        .ToArray();
}

Es ist das gleiche Prinzip, aber es wird Ihnen ein schöneres Ausnahme geben:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top