Ответ 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;
}
}