Как пропустить функцию с лямбда-кодом внутри? - PullRequest
7 голосов
/ 15 декабря 2010

Рассмотрим фрагмент ниже:

    [DebuggerStepThrough]
    private A GetA(string b)
    {
        return this.aCollection.FirstOrDefault(a => a.b == b);
    }

Если я использую F11, отладчик не пропускает функцию, а останавливается на ab == b .

IsЕсть ли способ перепрыгнуть через эту функцию, а не с помощью F10?

Ответы [ 4 ]

4 голосов
/ 05 ноября 2013

IMO, это ошибка в компиляторе C #.Компилятор также должен поместить эти атрибуты в анонимные методы.Обходной путь - вернуться к выполнению работы вручную, которую выполняет для вас компилятор C #:

[DebuggerStepThrough]
private A GetA(string b)
{
    var helper = new Helper { B = b };

    return this.aCollection.FirstOrDefault(helper.AreBsEqual);
}

private class Helper
{
    public string B;

    [DebuggerStepThrough]
    public bool AreBsEqual(A a) { return a.b == this.B; }
}

Но, конечно, это неприятно и совершенно нечитабельно.Вот почему компилятор C # должен был сделать это.Но, конечно, сложный вопрос для команды C #: какие атрибуты, которые вы помещаете в метод, должны быть скопированы во внутренние анонимные методы, а какие нет?

2 голосов
/ 15 декабря 2010

Я понимаю, почему это происходит, но у меня нет способа обойти это.Возможно, кто-то может опираться на это.Лямбда-выражение компилируется в анонимный метод.

Я вижу: Program.GetA.AnonymousMethod__0 (Test a)

Так же, как если бы вы вызвали другой метод в показанном вами методе, нажмитеF11 войдет в этот метод.например, /

[DebuggerStepThrough]
static A GetA<A>(IList<A> aCollection, string b) where A : Test
{
    DoNoOp();
    return aCollection.FirstOrDefault(a => a.b == b);
}

static void DoNoOp()
{
    // noop
    Console.WriteLine("got here");
}
0 голосов
/ 08 сентября 2014

Это беспокоило меня долгое время, сегодня я нашел способ сделать это, используя деревья выражений в .NET 4.0.

Рассмотрим следующий код:

private class Borked
{
    public object X 
    {
        [DebuggerStepThrough]
        get { throw new NotImplementedException(); }
    }
}

private void SomeMethod()
{
    var bad = new Borked();
    object obj = bad.TryGet(o => o.X);
}

Сейчас -- Я могу вызывать этот код, не пропуская удар - единственное место, которое отладчик попытается остановить, находится в свойстве сломанного получателя Borked - поэтому я добавил туда атрибут DebuggerStepThrough.

Вместо лямбды я беру дерево выражений (которое использует тот же синтаксис !!) и компилирую и запускаю его во время выполнения - это немного больше работы(едва), чем использование обычной лямбды, и она не будет работать для всех, но для простых запросов Linq и тому подобного она прекрасно работает.

Вся магия происходит в следующем методе - который, опять же,Первоначально использовался для принятия обычного аргумента Func<>, но он приостанавливал отладчик при возникновении исключения (несмотря на атрибут step-through), поэтому теперь я делаю это с Expression<Func<>>, например, так:

[DebuggerStepThrough]
public static T TryGet<OT, T>(this OT obj, params Expression<Func<OT, T>>[] getters)
{
    T ret = default(T);

    if (getters != null)
    {
        foreach (var getter in getters)
        {
            try
            {
                if (getter != null)
                {
                    var getter2 = (Func<OT, T>)getter.Compile();
                    ret = getter2(obj);
                    break;
                }
            }
            catch
            { /* try next getter or return default */ }
        }
    }

    return ret;
}

Это верно - вы просто вызываете .Compile() и приводите возвращаемое значение к обычному Func<>, который вы можете немедленно вызвать !!- Насколько легко это было?!

В моей реализации я позволил пользователю передавать несколько параметров, чтобы у них был способ получить запасное значение (и чтобы это запасное значение только создавалось / оценивалось * 1022)* IF обязательно).

Кроме того, я не уверен, является ли причина подавления события отладки из-за VisualStudio «Просто мой код», или потому что он запускается встроенным в этом методе.... но в любом случае это чертовски хорошо работает, черт побери !!

Теперь я предполагаю, что вызов этого метода .Compile для выражения во время выполнения не супер быстрый, но вНа практике это, похоже, не добавляет мне никакого снижения производительности в моих запросах.Итак, я очень взволнован (прошу прощения за множественные / избыточные удары и интеробанги и т. Д.)

0 голосов
/ 15 декабря 2010

Я не уверен, что это работает, но вы можете попробовать поместить атрибут в лямбда-выражение

[DebuggerStepThrough]
private A GetA(string b)
{
    return this.aCollection.FirstOrDefault([DebuggerStepThrough]a => a.b == b);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...