C#类型后面的尾随点表示什么?

22

我一直在调试与 Razor View 引擎相关的代码,发现某些类型名称以点号结尾,例如:

{Nancy.ViewEngines.Razor.RazorViewEngine.}

有人知道这表示什么吗?在对象的强制类型转换中使用它不是有效的语法,我很想知道在调试器中它表示什么。

编辑:根据 @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视图缓存中添加日志记录,以调查Razor视图抛出编译错误的间歇性问题,但这与问题并不相关。


这个库可以自动生成代码。如果你能看到 System.CodeDom,也许还有一些 Reflection.Emit,那么你已经了解了一半。如果遇到问题,请向 该项目 提交错误报告。 - Hans Passant
一个愚蠢的 ToString() 实现是我的猜测。在观察窗口中查看实际类型。 - leppie
@leppie ToString 可能会返回类似 "Nancy.ViewEngines.Razor.RazorViewEngine+<>c__DisplayClass1" 的内容。它是命名空间为 Nancy.ViewEngines.Razor 中类型为 RazorViewEngine 的嵌套类 <>c__DisplayClass1。调试器尝试写出外部类,后跟句点(而不是加号),然后是内部类名称,而不是调用 ToString()。请参见 Damien 更新的答案。 - Jeppe Stig Nielsen
1个回答

12

当变量/值实际上是编译器生成的类型(例如用于保存由lambda、async、iterator等捕获的“局部变量”)时,我曾见过这种情况发生。在各个地方的调试器似乎无法显示实际的类名。


例如,这个示例程序:

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;
  }
}

所以你的意思是真实的类型名称实际上是Nancy.ViewEngines.Razor.RazorViewEngine.STRANGE_CHARS_HERE,但由于一个 bug,显示出来的只有Nancy.ViewEngines.Razor.RazorViewEngine. - Jeppe Stig Nielsen
1
@JeppeStigNielsen - 这就是我所见到的情况 - 例如,如果类型名称为<>displayClass1,那么该类型的值仅在类型列中显示命名空间名称。当然,获取这些类型的实例有点棘手,而且如果OP没有展示更多的代码,我们就不知道是否真的是这种情况。不幸的是,生成一个问题的简短演示也很棘手。 - Damien_The_Unbeliever
我会尝试在今天抽出时间,通过调试器逐步执行并截取屏幕截图,敬请关注... - Henry Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接