Подтвердить что ты не робот

Что указывает конечная точка на С#?

Я искал некоторый код в отладчике, связанном с движком Razor View, и я заметил, что некоторые из типов появляются в Debugger с символом концевой точки в конце имени типа, например:

{Nancy.ViewEngines.Razor.RazorViewEngine.}

Кто-нибудь знает, что это означает? Это недействительный синтаксис, чтобы использовать его при указании на объект, поэтому я заинтригован относительно того, что он указывает в отладчике.

EDIT: по просьбе @Damien_The_Unbeliever снимок экрана с переменной в отладчике:

Debug Image

И код, на который я смотрю:

public TCompiledView GetOrAdd<TCompiledView>(
            ViewLocationResult viewLocationResult, Func<ViewLocationResult, TCompiledView> valueFactory)
        {
            TCompiledView compiledView = default(TCompiledView);
            compiledView = (TCompiledView)this.cache.GetOrAdd(viewLocationResult, x => valueFactory(x));

Чтобы дать немного больше информации, мы пытаемся добавить журнал в наш Nancy View Cache, чтобы исследовать прерывистую проблему с Razor Views, бросая ошибки компиляции, но это не имеет отношения к вопросу.

4b9b3361

Ответ 1

Я видел, как это произошло, когда переменная/значение действительно относится к сгенерированному компилятором типу (например, для хранения "локальных переменных", захваченных лямбдой, асинхронным, итератором и т.д.). Отладчик (в разных местах) кажется неспособным отобразить фактическое имя класса.


например. эта примерная программа:

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.DoStuff();
    }

    void DoStuff()
    {
        int i = 19;
        Expression<Func<int>> j = () => i + 10;
        var k = (((j.Body as BinaryExpression).Left as MemberExpression).Expression as ConstantExpression).Value;
        Console.ReadLine();
    }
}

С точкой останова на Console.ReadLine() вы обнаружите, что тип класса k выглядит как Program., а не Program+<>_DisplayClass0


Добавление Jeppe: этот пример - небольшое упрощение вышеизложенного, избегая дерева выражений. Посмотрите на экземпляр делегата Target, который будет экземпляром сгенерированного класса. Для сравнения также рассматривается тип блока итератора:

using System;
using System.Collections.Generic;

static class Program
{
  static void Main()
  {
    int i = 19; // to be captured by lambda, will become field on a generated class
    Func<int> f = () => i;
    var target = f.Target;  // when debugging type looks like "Program."
    Console.WriteLine(target.GetType().ToString()); // writes "Program+<>c__DisplayClass1"

    var seq = GetSeq();  // when debugging type looks like "Program.GetSeq"
    Console.WriteLine(seq.GetType().ToString()); // writes "Program+<GetSeq>d__3"
  }

  static IEnumerable<int> GetSeq() // returns "state machine" (iterator block)
  {
    yield return 42;
  }
}